有没有正则表达式可以匹配包含 A 但不包含 B 的字符串?

52

我的问题是我想用纯正则表达式来检查浏览器字符串。

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
什么语言,正则表达式风格?http://www.regular-expressions.info/tools.html - sehe
这并不容易:http://stackoverflow.com/q/8186424/241506 - VMykyt
你想用 (?:[^])*? 表达什么? - stema
3个回答

102

您可以使用前瞻断言来检查字符串中是否包含某个单词。

如果您想确保字符串在某个地方包含“Android”,可以像这样做:

^(?=.*Android).*

您也可以将它们组合起来,以确保它在某个位置包含"Android"和在某个位置包含"Mobile":

^(?=.*Android)(?=.*Mobile).*
如果您想确保字符串中不包含特定的单词,请使用否定向前查看:
^(?=.*Android)(?!.*Mobile).*
这需要字符串中包含单词"Android",并且不允许出现单词"Mobile"。当开头的断言为真时,.*部分匹配整个字符串/行。
在Regexr上查看此处.

3

在某些正则表达式的实现中,您可以使用负回顾断言。根据文档,写作(?<!...)的负回顾断言仅在当前位置的字符串未被匹配为...时才匹配。

以下是一个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

1

我只是打破它

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)

请注意查看前瞻/后顾


更新已经使用 Perl5 正则表达式引擎测试通过(可能是最流行的正则表达式引擎):

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

显示:

1 yes

针对 OP 中给出的输入


现在使用Perl5兼容的正则表达式进行了测试。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接