Существует ли регулярное выражение для сопоставления строки, содержащей A, но не содержащей B - PullRequest
33 голосов
/ 23 ноября 2011

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

Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13

-> должно соответствовать

Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 

не должно совпадать

Мое проверенное решение: /?((?<=Android)(?:[^])*?(?=Mobile))/i но это в точности совпадает.

Ответы [ 3 ]

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

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

Если вы хотите убедиться, что строка содержит «Android» в каком-то месте, вы можете сделать это следующим образом:

^(?=.*Android).*

Вы также можете комбинировать их, чтобы убедиться, что они содержат «Android» в некотором месте и «Мобильный» в некотором месте:

^(?=.*Android)(?=.*Mobile).*

Если вы хотите убедиться, что определенное слово НЕ содержится в строке, используйте отрицательный взгляд вперед:

^(?=.*Android)(?!.*Mobile).*

Для этого потребуется, чтобы слово «Android находилось в строке, а слово« Mobile »не допускалось в строке. Часть .* соответствует полной строке / строке, когда утверждения в начале верны».

Посмотрите это здесь, на Regexr

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

В некоторых реализациях регулярных выражений вы можете использовать отрицательное утверждение за утверждением. Согласно документам, отрицательный вид сзади, записанный как (?<!...), соответствует, только если текущей позиции в строке не предшествует совпадение для ...

Вот интерактивный скрипт Python, показывающий, как использовать отрицательный внешний вид с вашими примерами строк:

>>> s = "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13"
>>> bool(re.search(r'Android.*(?<! Mobile) Safari', s))
True

>>> t = "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
>>> bool(re.search(r'Android.*(?<! Mobile) Safari', t))
False
2 голосов
/ 23 ноября 2011

Я бы просто разбил его на части

if ((m/Android/i) && (m/Safari/i) && !(m/Mobile Safari/i))

Тем не менее, в зависимости от языка регулярных выражений, вы можете комбинировать это

if ((m/Android/i) && (m/(?<!Mobile )Safari/i))

или даже

if (m/Android.*(?<!Mobile )Safari/i)

К вашему сведению Lookahead / lookbehind


Обновление Протестировано это с использованием регулярного выражения Perl5 (возможно, самый популярный):

perl -ne 'print "$. yes\n" if m/Android.*(?<!Mobile )Safari/i'

Показывает:

1 yes

для заданного ввода в OP

...