Регулярное выражение для поиска двух строк в любом месте ввода - PullRequest
39 голосов
/ 08 февраля 2010

Как написать регулярное выражение для соответствия двум заданным строкам в любой позиции строки?

Например, если я ищу cat и mat, оно должно совпадать:

The cat slept on the mat in front of the fire.
At 5:00 pm, I found the cat scratching the wool off the mat.

Неважно, что предшествует этим строкам.

Ответы [ 7 ]

61 голосов
/ 08 февраля 2010
/^.*?\bcat\b.*?\bmat\b.*?$/m

Использование модификатора m (обеспечивающего совпадение метасимволов начала / конца при переносе строки, а не в самом начале и конце строки):

  • ^ соответствует началу строки
  • .*? соответствует чему-либо в строке до ...
  • \b соответствует границе слова с первым появлением границы слова (как обсуждалось @codaddict)
  • затем строка cat и граница другого слова; обратите внимание, что подчеркивания рассматриваются как символы «слова», поэтому _cat_ будет , а не match *;
  • .*?: любые символы до ...
  • граница, mat, граница
  • .*?: все оставшиеся символы до ...
  • $: конец строки.

Важно использовать \b, чтобы гарантировать, что указанные слова не являются частью более длинных слов, и важно использовать не жадные символы подстановки (.*?) по сравнению с жадными (.*), потому что последнее не сработает Строки типа «На коврике есть кот, который находится под котом». (Это будет соответствовать последнему появлению «кота», а не первому.)

* Если вы хотите совпадать с _cat_, вы можете использовать:

/^.*?(?:\b|_)cat(?:\b|_).*?(?:\b|_)mat(?:\b|_).*?$/m

, что соответствует либо подчеркиванию , либо границ слов вокруг указанных слов. (?:) обозначает группу без захвата, которая может помочь с производительностью или избежать конфликтных захватов.

Редактировать: В комментариях был задан вопрос о том, будет ли решение работать для фраз, а не только для слов. Ответ абсолютно да. Следующее будет соответствовать «Строка, которая включает в себя как первую фразу, так и вторую фразу»:

/^.*?(?:\b|_)first phrase here(?:\b|_).*?(?:\b|_)second phrase here(?:\b|_).*?$/m

Редактировать 2: Если порядок не имеет значения, вы можете использовать:

/^.*?(?:\b|_)(first(?:\b|_).*?(?:\b|_)second|second(?:\b|_).*?(?:\b|_)first)(?:\b|_).*?$/m

И если производительность действительно является проблемой здесь, возможно, что обходной путь (если ваш движок регулярных выражений поддерживает его) может (но, вероятно, не будет) работать лучше, чем выше, но я оставлю как возможно более сложную версию просмотра, так и Тестирование производительности как упражнение для спрашивающего / читателя.

Отредактировано согласно комментарию @Alan Moore. У меня не было возможности проверить это, но я верю вашему слову.

20 голосов
/ 08 февраля 2010
(.* word1.* word2.* )|(.* word2.* word1.*)
5 голосов
/ 14 августа 2015

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

/(?=.*?(string1))(?=.*?(string2))/is

Модификатор i = регистронезависимый

. *? Ленивая оценка для любого персонажа (соответствует как можно меньше)

? = Для Positive LookAhead оно должно где-то совпадать

s модификатор =. (Точка) также принимает переносы строк

4 голосов
/ 08 февраля 2010

Вы можете попробовать:

\bcat\b.*\bmat\b

\b является якорем и соответствует границе слова . Он будет искать слов cat и mat в любом месте строки, а mat следует за cat. Это не будет соответствовать:

Therez caterpillar on the mat.

но будет соответствовать

The cat slept on the mat in front of the fire

Если вы хотите сопоставить строки, в которых есть буквы cat и затем mat, вы можете попробовать:

cat.*mat

Это будет соответствовать обеим приведенным выше строкам примера.

2 голосов
/ 19 ноября 2014

Это достаточно просто для требуемой вычислительной мощности:

(string1(.|\n)*string2)|(string2(.|\n)*string1)

Я использовал это в visual studio 2013, чтобы найти все файлы, в которых были как строки 1, так и 2.

1 голос
/ 08 февраля 2010

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

>>> for line in open("file"):
...     g=0;f=0
...     s = line.split()
...     for item in s:
...         if item =="cat": f=1
...         if item =="mat": g=1
...     if (g,f)==(1,1): print "found: " ,line.rstrip()

found:  The cat slept on the mat in front of the fire.
found:  At 5:00 pm, I found the cat scratching the wool off the mat.
0 голосов
/ 19 августа 2014

Это работает для поиска файлов, которые содержат как String1, так и String2

(((|. \ П) ) String1 ((|. \ П) ) String2) | (((|. \ П) ) String2 ((|. \ П) ) String1)

Соответствует любому количеству символов или строковых полей затем String1 с последующим любым количеством символов или строковых полей затем String2 ИЛИ ЖЕ Подберите любое количество символов или строковых полей затем String2 с последующим любым количеством символов или строковых полей затем String1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...