Существует ли регулярное выражение для соответствия строке, содержащей A, но не содержащей B
Моя проблема в том, что я хочу проверить строку браузера с чистым регулярным выражением.
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
но он точно соответствует ошибкам.
Ответы
Ответ 1
Вы используете прогнозные утверждения, чтобы проверить, содержит ли строка слово или нет.
Если вы хотите убедиться, что строка содержит "Android" в каком-то месте, вы можете сделать это следующим образом:
^(?=.*Android).*
Вы также можете комбинировать их, чтобы убедиться, что он содержит "Android" в каком-то месте И "Мобильный" в каком-либо месте:
^(?=.*Android)(?=.*Mobile).*
Если вы хотите убедиться, что определенное слово НЕ в строке, используйте негативный прогноз вперед:
^(?=.*Android)(?!.*Mobile).*
Для этого потребуется слово "Android" в строке, а слово "Mobile" в строке не допускается. Часть .*
соответствует полной строке/строке, когда утверждения в начале являются истинными.
Смотрите здесь, в Regexr
Ответ 2
Я бы просто сломал его
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)
FYI см. Lookahead/lookbehind
Обновление Протестировано с помощью аромата Perge5 regex (возможно, самый популярный вкус):
perl -ne 'print "$. yes\n" if m/Android.*(?<!Mobile )Safari/i'
Показывает:
1 yes
для данного входа в OP
Ответ 3
С некоторыми реализациями регулярных выражений вы можете использовать отрицательное утверждение lookbehind.
В документах отрицательный lookbehind, записанный как (?<!...)
, соответствует только если текущей позиции в строке не предшествует совпадение для ...
Здесь Python interactive script показывает, как использовать отрицательный lookbehind с вашими примерами строк:
>>> 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