【问题标题】:Is there a regex to match a string that contains A but does not contain B [duplicate]是否有正则表达式来匹配包含 A 但不包含 B 的字符串 [重复]
【发布时间】:2012-01-04 15:51:49
【问题描述】:

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

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 但它完全匹配错误。

【问题讨论】:

标签: regex contains inverse


【解决方案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)

仅供参考Lookahead/lookbehind


更新用 Perl5 正则表达式风格(可以说是最流行的风格)对这些进行了很好的测试:

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

演出:

1 yes

对于 OP 中的给定输入

【讨论】:

  • 现在用兼容 Perl5 的正则表达式对其进行了测试
【解决方案2】:

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

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

^(?=.*Android).*

您也可以将它们组合起来,以确保它在某个地方包含“Android”并且在某个地方包含“Mobile”:

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

如果要确保某个单词不在字符串中,请使用否定前瞻:

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

这将要求字符串中包含单词“Android”,并且字符串中不允许包含单词“Mobile”。当开头的断言为真时,.* 部分匹配完整的字符串/行。

here on Regexr

【讨论】:

  • +1 表示最简单的纯正则表达式方法,但我将其写为^(?=.*Android)(?!.*Mobile).*。否则,将在每个位置应用前瞻,或者直到它们都成功。您的正则表达式按预期工作,因为除了开始之外,积极的前瞻总是失败,但如果您只有消极的前瞻怎么办?
  • @AlanMoore 感谢您的建议,我使用它编辑了我的答案。
  • @Stema 感谢您的精彩解释。今天学到了一些新东西。
  • Дай тебе бог здоровья!
【解决方案3】:

通过一些正则表达式的实现,您可以使用否定的lookbehind 断言。 根据文档,写为(?&lt;!...) 的负向lookbehind 仅在字符串中的当前位置之前没有匹配... 时才匹配

这是一个 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多