J'ai besoin d'une expression régulière qui corresponde à blahfooblah
mais pas à blahfoobarblah
Je veux que cela corresponde à foo et à tout ce qui se passe autour de foo, tant que ce n'est pas suivi de bar.
J'ai essayé d'utiliser ceci: foo.*(?<!bar)
qui est assez proche, mais il correspond à blahfoobarblah
. Le regard négatif derrière doit correspondre à tout et pas seulement à la barre.
Le langage spécifique que j'utilise est Clojure, qui utilise des regex Java sous le capot).
EDIT: Plus spécifiquement, j'en ai aussi besoin pour passer blahfooblahfoobarblah
mais pas blahfoobarblahblah
.
/(?!.*bar)(?=.*foo)^(\w+)$/
blahfooblah # pass
blahfooblahbarfail # fail
somethingfoo # pass
shouldbarfooshouldfail # fail
barfoofail # fail
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
Si vous voulez seulement exclure bar
alors que c'est juste après foo
, vous pouvez utiliser
/(?!.*foobar)(?=.*foo)^(\w+)$/
Vous avez mis à jour votre question pour la rendre spécifique.
/(?=.*foo(?!bar))^(\w+)$/
fooshouldbarpass # pass
butnotfoobarfail # fail
fooshouldpassevenwithfoobar # pass
nofuuhere # fail
(?=.*foo(?!bar))
s'assure qu'un foo
est trouvé mais n'est pas suivi directement bar
Pour faire correspondre un foo
à un événement qui ne commence pas par bar
, essayez
foo(?!bar)
Votre version avec lookbehind négatif est effectivement "correspond à un foo
suivi de quelque chose qui ne se termine pas par bar
". Le .*
correspond à tous les barblah
, et le (?<!bar)
revient sur lah
et vérifie qu'il ne correspond pas à bar
, ce qui n'est pas le cas, donc tout le motif correspond.
Utilisez plutôt un regard négatif devant vous:
\s*(?!\w*(bar)\w*)\w*(foo)\w*\s*
Cela a fonctionné pour moi, espérons que cela aide. Bonne chance!
Vous avez écrit un commentaire suggérant que vous aimiez travailler ainsi en faisant correspondre tous les mots d'une chaîne plutôt que la chaîne entière elle-même.
Plutôt que d’écrire tout cela dans un commentaire, je l’affiche comme une nouvelle réponse.
/(?=\w*foo(?!bar))(\w+)/
foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere etnofuu needsfoo
foowithbar fooevenwithfoobar foohere butfooisokherebar needsfoo
Votre demande de correspondance spécifique peut être associée à:
\w+foo(?!bar)\w+
Cela correspondra à blahfooblahfoobarblah
mais pas à blahfoobarblahblah
.
Le problème avec votre regex de foo.*(?<!bar)
est le .*
Après foo
. Il correspond à autant de caractères, y compris les caractères après bar
.