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