我有一些正则表达式的经验,但已经有一段时间了.我写了一个复杂的表达式,试图匹配我认为无效的产品代码中的某些模式.我运行了几千个代码来验证它,我发现了一些不按预期运行的情况.
我把它缩小到一个特定的问题,我在下面以简化的方式介绍 - 这是我不理解的概念,而不是我正在使用的实际表达.我想找到以某种方式启动的代码,在中间包含可选组件(但如果它们确实存在,它们必须完全匹配某个模式 - 我不能只是贪婪地匹配任何东西),但是不能正确结束(应该结束于"d"但不是).顺便说一下,它通过Windows脚本主机在(gag)VBScript中实现.
^a(b)?(c)?(?!d$)
Run Code Online (Sandbox Code Playgroud)
应该匹配的事情:
不应该匹配的事情:
基本上,"ae"匹配正确,但任何一个或两个选项应该匹配时,它会导致整个匹配失败.我认为这与贪婪本性有关?但一直无法弄清楚如何让它发挥作用.同样,我不能使用类似下面的内容 - 如果组件存在于"a"和"e"之间,则它们必须完全是"b"或"c".
^a(?!.*d$)
Run Code Online (Sandbox Code Playgroud)
谢谢!
我认为通过"失败"你的意思是abd匹配它不应该.首先,让我们看看为什么会这样:
a 火柴 ab 火柴 (b)?d不匹配(c)?,但好的,它是可选的(?!d$)失败是因为我们在d字符串结尾之前就是正确的.所以这种方法不起作用.现在的问题是正则表达式引擎尚未尝试的另一种可能性,所以它回溯到之前的位置b:(b)?匹配b,因为它是可选的.b也不匹配(c)?.好的,它是可选的.(?!d)成功是因为我们在cd字符串末尾之前就是正确的,但这并不匹配d$.成功!所以,你可以做什么?如果你可以使用负面的lookbehind断言会很好,但唉,ECMAScript正则表达不支持它.
下一个最好的方法是将负向前瞻放在正则表达式的开头:
^(?!.*d$)a(b)?(c)?
Run Code Online (Sandbox Code Playgroud)
首先要确保字符串不以d.只有这样才能开始实际匹配.现在,这会传递所有测试用例.