Regex оглянуться вокруг - Java

Я унаследовал некоторое регулярное выражение и пытался понять, почему он соответствует определенному шаблону. Следующее регулярное выражение основано на положительном прогнозном утверждении и соответствующем тексте, например bear grylls episode, Это имеет смысл. Но это также соответствует тексту, где episode сопровождается bear gryllsнапример, episode bear grylls, Я не вижу никакой ссылки, чтобы оглянуться назад в регулярном выражении. является .*? в конце концов, заставляя его оглянуться назад?

^(?=.*?bear grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?

3 ответа

Это объясняет, что он делает.
Чтобы изменить, это зависит от того, что вы хотите сделать.

Это то, что он сейчас делает -

 # ^(?=.*?bear\ grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?

 ^                             # Beginning of string
 (?=                           # Look ahead
      .*?                           # Ungreedy, any number of characters
      bear\ grylls                  # Must be 'bear grylls' somewhere
 )                             # End lookahead
 (?=                           # Look ahead
      .*?                           # Ungreedy, any number of characters
      (                             # (1 start), Must be one of these somewhere
           \b nbc \b 
        |  reality
        |  episode
        |  show
        |  watch
        |  series
        |  season
        |  premiere
      )                             # (1 end)
 )                             # End lookahead
 .*?                           # Assertions passed tests, now match the entire string

Я бы изменил это, чтобы получить немного лучшую функциональность -

 # (?s)^(?=.*\bbear\ grylls\b)(?=.*\b(nbc|reality|episode|show|watch|series|season|premiere)\b).*

 (?s)                          # Dot all modifier
 ^                             # Beginning of string
 (?=                           # Look ahead
      .*                            # Greedy, any number of characters
      \b bear\ grylls \b            # Must be 'bear grylls' 
 )                             # End lookahead
 (?=                           # Look ahead
      .*                            # Greedy, any number of characters
      \b 
      (                             # (1 start), Must be one of these
           nbc 
        |  reality
        |  episode
        |  show
        |  watch
        |  series
        |  season
        |  premiere
      )                             # (1 end)
      \b 
 )                             # End lookahead
 .*                            # Assertions passed tests, now match the entire string

Я предлагаю использовать RegexFormat 5, где он форматирует и создает авто-комментарии.

Все прогнозные и прогнозные утверждения (?=...), (?!...), (?<=...), (?<!...) не потребляет текст. Он не продвигает указатель на текущую позицию, что является нормальным поведением при сопоставлении некоторого текста.

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

В вашем случае регулярное выражение проверяет наличие строки bear gryllsЗатем он проверяет наличие какой-либо строки во втором предварительном просмотре.

Без заблаговременности, регулярное выражение станет:

^.*?bear grylls.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)|^.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere).*?bear grylls

поскольку bear grylls может прийти до или после любой из строк в списке, вы должны проверить оба случая поочередно. Проблема СУХОГО может быть решена путем конкатенации строк, но когда она недоступна, людям будет сложно проводить техническое обслуживание.

Это также метод, часто используемый при проверке пароля, когда может быть несколько условий, таких как, по крайней мере, один алфавит, по крайней мере, одна цифра, по крайней мере, один специальный символ, нет 3 одинаковых символов в строке и т. Д. Если вы хотите написать одно выражение, чтобы проверить все свойства выше, это очень грязно. Использование упреждающего утверждения позволяет вам втиснуть все в одно выражение, не делая регулярное выражение непонятным и неосуществимым.

Лично я не слишком люблю этот подход, так как нет смысла втискивать все в одно регулярное выражение, если вы не ограничены инструментом и не можете запускать несколько регулярных выражений. Мы можем просто сделать 2 регулярных выражения и проверить строку против каждого. Производительность будет примерно одинаковой, поскольку в движке регулярных выражений выполняется столько же работы. На самом деле, я полагаю, что большинство двигателей дважды проверят строку в приведенном выше регулярном выражении.

Я переписываю ваше оригинальное регулярное выражение, которое может иметь желаемый результат

^(?=.*?bear grylls).+(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?

Это очень похоже на предыдущий. Единственное отличие состоит в том, что я добавляю ".+" Между двумя положительными утверждениями, которые приведут в исполнение последовательность этих двух частей, например, "эпизод с медвежьим грилем" будет иметь положительный результат, а "эпизод с медвежьим грилем" - нет.

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

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