Regex: sich überlappende Treffer finden

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Translating-IT.

    Regex: sich überlappende Treffer finden

    Hallo,

    ist es mit Regex möglich sich überlappende Treffer als einzelne Matches zu finden?

    Mit diesem Regex (.+)\b\1\b sollen Wortdopplungen oder Dopplungen von Wortgruppen gefunden werden. Funktioniert an sich recht gut, aber was, wenn sich solche Dopplungen überschneiden?

    Beispiel: Er ging ging für ging für 5 Euro Eis kaufen.

    Hier sollte entsprechend ging ging und ging für ging für erkannt werden, angezeigt wird aber nur ging ging.

    Bei diesem Satz funktionieren klarerweise beide:

    Er ging ging, ging für ging für 5 Euro Eis kaufen.

    Edit: Ach Gott, ich vergiss mal wieder die Hälfte. An sich sollte es mit einem positive Lookahead funktionieren, aber ich bekomms nicht hin.

    Edit2: Zur Not muss halt 2 unterschiedliche Abfragen (eine für Wortdopplungen und eine für Dopplungen von Wortgruppen) laufen lassen, aber was, wenn nun ein Wort/eine Wortgruppe 3 Mal oder öfter hintereinander vorkommt?

    LG,
    Pascal
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Translating-IT“ ()

    Die Regex-Engine geht nach einem Match immer so viel weiter wie das Match lang war. Grundsätzlich ist das also erstmal nicht möglich, wenn die beiden Treffer überlappend sind. Was du machen kannst, ist dein ganzes Regex-Pattern zero-length zu machen (alles in Lookaheads/Lookbehinds stecken), wie du erwähnt hattest ((?=(.+)\b\1\b)). Wenn der gesamte Match zero-length ist, geht die Regex-Engine soweit ich weiß nur ein Zeichen weiter, bevor es versucht, den nächsten Match zu finden (damit würde es also dein Beispiel matchen, aber nicht bei 4 mal ging nur zwei Mal ging ging und nicht die Variante, wo zwei Gruppen von je zwei Mal ging gematcht werden ((ging ging) (ging ging)), weil da zwei Matches am gleichen Punkt anfangen.

    Edit: Um nicht Leerzeichen-Patterns immer mit zu matchen, würde ich das ​.+ noch in ​\S.* ändern, also ein nicht-Whitespace-Zeichen und dann beliebige andere. Wahrscheinlich matcht das, wenn du das nicht so machst, viel zu viele Varianten.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nafets“ ()

    Hallo Nafets,

    das mit dem Lookahead funktioniert nur leider nicht. Zumindest habe ich keine Version gefunden, die funktionieren würde.

    Die Leerzeichen mit drinnen zu haben ist gewollt, da sonst einige Matches bei anderen Beispielen nicht erkannt werden.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Hm, das ist komisch. Wenn ich das Pattern, das ich gepostet hab, in nen Regex-Tester rein mache, funktioniert es: regex101.com/r/dYEAPx/1

    Leider habe ich gerade keine .NET-Entwicklungsumbegung zur Hand, um es selbst zu testen, aber eigentlich sollte es doch in .NET genauso funktionieren?
    ich hab's im RegexBuddy getestet, funktioniert irgendwie nicht mit C# .Net Core
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Überlappungen funktionieren zwar noch immer nicht, aber zumindest kann ich jetzt mal das Problem mit Wiederholungen gelöst, wo das Wort oder die Gruppe öfter als 2 Mal hintereinander vorkommt:

    (.{2,})\1(\1)?
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Und dank der Hilfe aus einem spezialisierten Regex-Forum gelöst:

    Wiederholungen über mehr als 2 hinweg geht sogar noch kürzer:

    (.{2,})(\1)+

    Und für die Überlappungen muss der Lookahead beim 2. Match gesetzt werden:

    (.{2,})(?=\1+)
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.