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

thr*_*joe 2 regex vbscript

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

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

^a(b)?(c)?(?!d$)
Run Code Online (Sandbox Code Playgroud)

应该匹配的事情:

  • AE
  • 安倍晋三
  • 高手
  • ABCE

不应该匹配的事情:

  • 广告
  • ABD
  • ACD
  • A B C D
  • AFE
  • ABFE
  • ACFE
  • abcfe

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

^a(?!.*d$)
Run Code Online (Sandbox Code Playgroud)

谢谢!

Tim*_*ker 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$.成功!

所以,你可以做什么?如果你可以使用负面的lookbehind断言会很好,但唉,ECMAScript正则表达不支持它.

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

^(?!.*d$)a(b)?(c)?
Run Code Online (Sandbox Code Playgroud)

首先要确保字符串不以d.只有这样才能开始实际匹配.现在,这会传递所有测试用例.