Ein regulärer Ausdruck für eine Teilzeichenfolge, auf die keine bestimmte andere Teilzeichenfolge folgt

115

Ich brauche eine Regex, die passt, blahfooblahaber nichtblahfoobarblah

Ich möchte, dass es nur zu foo und allem um foo passt, solange es nicht von einem Balken gefolgt wird.

Ich habe versucht, dies zu verwenden: Das foo.*(?<!bar)ist ziemlich nah, aber es passt blahfoobarblah. Der negative Blick dahinter muss zu allem passen und nicht nur zur Bar.

Die spezifische Sprache, die ich verwende, ist Clojure, die Java-Regexes unter der Haube verwendet.

EDIT: Genauer gesagt, ich brauche es auch zu bestehen, blahfooblahfoobarblahaber nicht blahfoobarblahblah.

Rayne
quelle
1
Haben Sie versucht, foo. * (? <! Bar. *) Zu verwenden?
Thibault Falise

Antworten:

157

Versuchen:

/(?!.*bar)(?=.*foo)^(\w+)$/

Tests:

blahfooblah            # pass
blahfooblahbarfail     # fail
somethingfoo           # pass
shouldbarfooshouldfail # fail
barfoofail             # fail

Erklärung des regulären Ausdrucks

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    bar                      'bar'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    foo                      'foo'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Andere Regex

Wenn Sie nur ausschließen möchten, barwenn es direkt danach ist foo, können Sie verwenden

/(?!.*foobar)(?=.*foo)^(\w+)$/

Bearbeiten

Sie haben Ihre Frage aktualisiert, um sie spezifisch zu gestalten.

/(?=.*foo(?!bar))^(\w+)$/

Neue Tests

fooshouldbarpass               # pass
butnotfoobarfail               # fail
fooshouldpassevenwithfoobar    # pass
nofuuhere                      # fail

Neue Erklärung

(?=.*foo(?!bar))stellt sicher, dass a foogefunden wird, aber nicht direkt verfolgt wirdbar

maček
quelle
Dies ist sehr nah und eine sehr gute Antwort. Ich wusste, dass ich nicht spezifisch genug sein würde. :( Ich brauche das: "blahfoomeowwoof / foobar /", um wegen des einsamen "foo" zu bestehen, aber nicht dieses blahfoobarmeowwoof, wenn dies möglich ist.
Rayne
Als Nebenfrage, wie würde man vorgehen, um etwas wie "Bot", aber nicht "Botters" zusammenzubringen?
Rayne
Ja. Ich kann das verwenden, was ich jetzt habe, aber es wäre einfacher, wenn ich nur Bot, aber nicht Botters zusammenbringen könnte. Es tut mir sehr leid. Ich bin unerfahren mit Regexen und ich fürchte, ich finde langsam heraus, was ich selbst will. : p
Rayne
1
@ Rayne, das ist die gleiche Frage. In Ihrem obigen Beispiel wollten Sie übereinstimmen, fooaber nicht foobar. Zu passen, botaber nicht botters, würden Sie verwenden /(?=.*bot(?!ters))^(\w+)$/.
Maček
Nun, ich habe im Allgemeinen auf ganze Worte abgezielt. Wie gesagt, ich bin verwirrt darüber, was ich wirklich will und was wirklich möglich ist. So wird es funktionieren. Danke für die Zeit. :)
Rayne
55

Versuchen Sie es, um einer fooGefolgschaft etwas zuzuordnen, das nicht beginntbar

foo(?!bar)

Ihre Version mit negativem Lookbehind ist effektiv "Match a foogefolgt von etwas, das nicht endet bar". Das .*passt alle zusammenbarblah , und das (?<!bar)schaut zurück lahund prüft, ob es nicht übereinstimmt bar, was nicht, also stimmt das gesamte Muster überein.

Stevemegson
quelle
Also habe ich dies für einen regulären Ausdruck versucht, der der Zeichenfolge "hast du" entspricht, solange nicht "sagen" folgt. Es funktioniert, wenn zum Beispiel zwischen "hast du gesagt" und "hast du gedacht" unterschieden wird, aber nur "hast du" an sich wird nicht erfasst und sollte es auch. Irgendwelche Vorschläge?
Soosus
2

Verwenden Sie stattdessen einen negativen Blick nach vorne:

\s*(?!\w*(bar)\w*)\w*(foo)\w*\s*

Das hat bei mir funktioniert, hoffe es hilft. Viel Glück!

Audie
quelle
Einfacher, aber effektiver Regex, der auch zum Ausschließen sich wiederholender Zeichenfolgen ("foofoo") dient. Perfekt!
Jonas Byström
1

Sie haben einen Kommentar geschrieben, der vorschlägt, dass dies so funktioniert, dass alle Wörter in einer Zeichenfolge und nicht die gesamte Zeichenfolge selbst übereinstimmen.

Anstatt all dies in einem Kommentar zusammenzufassen, poste ich es als neue Antwort.

Neuer Regex

/(?=\w*foo(?!bar))(\w+)/

Beispieltext

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needfoo

Streichhölzer

Foowithbar Fooevenwithfoobar Foohere Butfooisokherebar Needsfoo

maček
quelle
0

Ihre spezifische Match-Anfrage kann abgeglichen werden durch:

\w+foo(?!bar)\w+

Dies wird blahfooblahfoobarblahaber nicht übereinstimmen blahfoobarblahblah.

Das Problem mit dem regulären Ausdruck von foo.*(?<!bar)der .*nach foo. Es werden so viele Zeichen wie möglich nachher abgeglichen bar.

dawg
quelle