Логический оператор AND с регулярным выражением php - PullRequest
5 голосов
/ 23 ноября 2011

Я бы хотел использовать своего рода логический оператор «И» в своем регулярном выражении.Я попробовал это:

(?=exp1)(?=exp2)

Но в PHP ?= не работает и нужно написать мою программу на языке PHP.Есть ли другой метод?Выражение должно совпадать, если присутствуют все условия и в любом порядке.Я не хочу писать каждую перестановку как:

(exp1)(exp2)(exp3)|(exp1)(exp3)(exp2)|....

Ответы [ 2 ]

9 голосов
/ 23 ноября 2011

PHP поддерживает прогнозные выражения.Вы, вероятно, используете их неправильно.

Предполагая, что вы хотите сопоставить строку, содержащую все три из foo, bar и baz, вам необходимо регулярное выражение

^(?=.*foo)(?=.*bar)(?=.*baz)

Это вернет совпадение для строк foobarbaz или barbazfoo и т. Д. Однако это совпадение будет пустой строкой (потому что просмотрщики не потребляют никаких символов).Если вы хотите, чтобы регулярное выражение возвращало саму строку, используйте

^(?=.*foo)(?=.*bar)(?=.*baz).*

, которая затем будет соответствовать всей строке, если она удовлетворяет всем трем критериям.

Я бы просто использовал

if (preg_match('/^(?=.*foo)(?=.*bar)(?=.*baz)/s', $subject)) {
    # Successful match
} else {
    # Match attempt failed
}

Обратите внимание, что это также будет соответствовать строке типа foonly bartender bazooka.Если вы этого не хотите (разрешив только чистые перестановки по одному каждому из трех выражений), вы можете сделать это с помощью небольшого трюка:

^(?:foo()|bar()|baz()){3}\1\2\3$

соответствует foobarbaz, foobazbar, barfoobaz, barbazfoo, bazfoobar и bazbarfoo (и ничего больше).«Уловка» вдохновлена ​​превосходной книгой Яна Гойваэрта и Стивена Левитана «Поваренная книга регулярных выражений» (с. 304).Он работает следующим образом:

  • За каждой требуемой частью (foo и т. Д.) Следует пустая группа захвата (), которая всегда совпадает, если требуемая часть соответствует.
  • Таким образом, если все три требуемые части совпали, все три пустые группы захвата совпали.
  • Следующие обратные ссылки успешны, только если каждая из групп захвата участвовала в матче.
  • Таким образом, если строка равна foobarbar, деталь (?:foo()|bar()|baz()){3} будет соответствовать, но \3 завершится ошибкой, поэтому общее регулярное выражение не выполнится.
  • Если, однако, все три действительно приняли участие в совпадении, \1\2\3 успешно сопоставляется в конце строки, поскольку каждая из групп захвата содержит только пустую строку.
1 голос
/ 23 ноября 2011

В дополнение к ответу @ Тима:

(?=exp1)(?=exp2)

Это никогда не может быть правдой.Вы говорите простым английским языком: убедитесь, что текст, приведенный здесь, является exp1, а также убедитесь, что текст, приведенный здесь, является exp2.Ни в коем случае это правда.Это никогда не будет совпадать.

...