Frage Eine Regex, die mit einer Teilzeichenfolge übereinstimmt, der keine bestimmte andere Teilzeichenfolge folgt


Ich brauche eine Regex, die passt blahfooblah aber nicht blahfoobarblah

Ich möchte, dass es nur foo und alles um foo passt, solange es nicht von bar gefolgt wird.

Ich habe es versucht: foo.*(?<!bar) Das ist ziemlich nah, aber es passt blahfoobarblah. Der negative Blick dahinter muss mit allem übereinstimmen und nicht nur bar.

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

EDIT: Genauer gesagt, ich brauche es auch zu übergeben blahfooblahfoobarblah aber nicht blahfoobarblahblah.


75
2018-04-13 15:48


Ursprung


Antworten:


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 bar wenn es direkt danach ist fookannst du benutzen

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

Bearbeiten

Sie haben Ihre Frage aktualisiert, um sie genauer zu machen.

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

Neue Tests

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

Neue Erklärung

(?=.*foo(?!bar)) gewährleistet a foo gefunden, wird aber nicht direkt befolgt bar


104
2018-04-13 15:51



Um zu einem zu passen foo gefolgt von etwas, das nicht mit beginnt bar, Versuchen

foo(?!bar)

Ihre Version mit negativem Lookbehind ist effektiv "match a foo gefolgt von etwas, das nicht endet bar". Das .* passt zu allen barblah, und das (?<!bar) schaut zurück lah und überprüft, dass es nicht übereinstimmt bar, was es nicht tut, also stimmt das ganze Muster überein.


39
2018-04-13 16:00



Verwenden Sie stattdessen einen negativen Blick:

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

Das hat für mich funktioniert, hoffe es hilft. Viel Glück!


2
2018-04-13 15:59



Ihre spezifische Abgleichsanfrage kann wie folgt abgeglichen werden:

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

Dies wird übereinstimmen blahfooblahfoobarblah aber nicht blahfoobarblahblah.

Das Problem mit deiner Regex von foo.*(?<!bar) ist der .* nach foo. Es passt so viele Zeichen wie Zeichen nach bar.


1
2018-04-13 16:21



Sie haben einen Kommentar geschrieben, der darauf hinweist, dass Sie so arbeiten, dass alle Wörter in einer Zeichenfolge und nicht die gesamte Zeichenfolge selbst übereinstimmen.

Anstatt all das in einen Kommentar zu packen, schreibe ich es als neue Antwort.

Neue Regex

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

Beispieltext

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhier undnofuu needsfoo

Streichhölzer

foowithbar fooevenwithfoobar foohere butfooisokherebar brauchtfoo


1
2018-04-13 17:23