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

Мне нужен regex, который будет соответствовать blahfooblah но нет blahfoobarblah

Я хочу, чтобы это соответствовало только нечто и всему вокруг нечто, пока это не сопровождается панелью.

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

Определенным языком, который я использую, является Clojure, который использует Java regexes под капотом.

Править: Строго говоря, мне также нужен он для передачи blahfooblahfoobarblah но нет blahfoobarblahblah.

100
задан Lii 16 February 2016 в 08:56
поделиться

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

141
ответ дан 24 November 2019 в 04:51
поделиться

Чтобы сопоставить foo , за которым следует что-то, что не начинается с bar , попробуйте

foo(?!bar)

Ваш версия с отрицательным ретроспективным просмотром эффективно «соответствует foo , за которым следует что-то, что не заканчивается на bar ». . * соответствует всем barblah , а (? смотрит назад на lah и проверяет, что это не ' t соответствует bar , чего нет, поэтому соответствует весь шаблон.

48
ответ дан 24 November 2019 в 04:51
поделиться

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

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

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

2
ответ дан 24 November 2019 в 04:51
поделиться

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

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

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

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

0
ответ дан 24 November 2019 в 04:51
поделиться

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

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

New Regex

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

Sample text

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needsfoo

Match

foowithbar fooevenwithfoobar foohere butfooisokherebar needsfoo

1
ответ дан 24 November 2019 в 04:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: