Регулярное выражение для соответствия подстроки, за которой не следует определенная другая подстрока

Мне нужно регулярное выражение, которое будет соответствовать blahfooblah но нет blahfoobarblah

Я хочу, чтобы он совпадал только с foo и всем вокруг foo, если за ним не стоит bar.

Я пытался использовать это: foo.*(?<!bar) что довольно близко, но это соответствует blahfoobarblah, Отрицательный взгляд должен совпадать с чем угодно, а не только с чертой.

Конкретный язык, который я использую, - это Clojure, который использует регулярные выражения Java под капотом.

РЕДАКТИРОВАТЬ: Более конкретно, мне также нужно, чтобы передать blahfooblahfoobarblah но нет blahfoobarblahblah,

5 ответов

Решение

Пытаться:

/(?!.*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

Другое регулярное выражение

Если вы хотите исключить bar когда это сразу после foo, ты можешь использовать

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

редактировать

Вы сделали обновление своего вопроса, чтобы сделать его конкретным.

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

Новые тесты

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

Новое объяснение

(?=.*foo(?!bar)) обеспечивает foo найден, но не отслеживается напрямую bar

Чтобы соответствовать foo после чего-то, что не начинается с bar, пытаться

foo(?!bar)

Ваша версия с негативным взглядом сзади "соответствует foo сопровождается чем-то, что не заканчивается bar". .* соответствует всем barblahи (?<!bar) оглядывается на lah и проверяет, что это не соответствует bar, чего нет, поэтому весь шаблон совпадает.

Вместо этого используйте отрицательный взгляд вперед:

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

Это сработало для меня, надеюсь, это поможет. Удачи!

Вы написали комментарий, предлагающий, чтобы вы работали так, чтобы соответствовать всем словам в строке, а не самой строке.

Вместо того, чтобы смешивать все это в комментарии, я публикую это как новый ответ.

Новый Регекс

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

Пример текста

Что бы там ни было, да и вообще, не так, как здесь.

Матчи

фоусбар

Ваш конкретный запрос на совпадение может быть сопоставлен:

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

Это будет соответствовать blahfooblahfoobarblah но нет blahfoobarblahblah,

Проблема с вашим регулярным выражением foo.*(?<!bar) это .* после foo, Он соответствует какому-либо количеству любых символов, включая символы после bar,

Другие вопросы по тегам