正则表达式:可选后跟负向前瞻

时间:2013-10-22 04:51:00

标签: regex vbscript

我有一些正则表达式的经验,但已经有一段时间了。我写了一个复杂的表达式,试图匹配我认为无效的产品代码中的某些模式。我在几千个代码上运行了我的代码来验证它,并且我发现了一些不符合预期的情况。

我把它缩小到一个特定的问题,我在下面以简化的方式介绍 - 这是我不理解的概念,而不是我正在使用的实际表达。我想找到以某种方式启动的代码,在中间包含可选组件(但如果它们存在,它们必须完全匹配某个模式 - 我不能只是贪婪地匹配任何东西),但是不能正确结束(应该结束于“d”但不是)。顺便说一下,它是通过Windows脚本主机在(gag)VBScript中实现的。

^a(b)?(c)?(?!d$)

应该匹配的事情:

  • AE
  • 安倍
  • ACE
  • ABCE

不应匹配的事情:

  • 广告
  • ABD
  • ACD
  • ABCD
  • AFE
  • ABFE
  • ACFE
  • abcfe

基本上,“ae”匹配正确,但只要其中一个或两个选项匹配,就会导致整个匹配失败。我认为这与贪婪本性有关?但一直无法弄清楚如何让它发挥作用。同样,我不能使用类似下面的内容 - 如果组件存在于“a”和“e”之间,它们必须完全是“b”或“c”。

^a(?!.*d$)

谢谢!

1 个答案:

答案 0 :(得分:7)

我认为“失败”是指abd匹配时不应该。首先,让我们看看为什么会这样:

  1. a匹配a
  2. b匹配(b)?
  3. d(c)?不匹配,但是好的,它是可选的
  4. (?!d$)失败,因为我们正好在字符串末尾的d之前。所以这种方法不起作用。现在的问题是正则表达式引擎尚未尝试的另一种可能性,因此它回溯到b之前的位置:
  5. 让我们尝试使用(b)?来匹配b,因为它是可选的。
  6. b也与(c)?不匹配。好的,它是可选的。
  7. (?!d)成功,因为我们在字符串末尾的cd之前,并且与d$不匹配。成功了!
  8. 那么,你能做什么?如果你可以使用negative lookbehind assertion会很好,但是唉,ECMAScript正则表达式不支持它。

    下一个最好的方法是将负前瞻置于正则表达式的开头:

    ^(?!.*d$)a(b)?(c)?
    

    首先确保字符串不以d结尾。只有这样才能开始实际匹配。现在,这将通过所有测试用例。