如何编写一个正则表达式来匹配一个可以包含引号的模式,但是如果有引号,则必须在开头和结尾处具有匹配的引号?
"?(pattern)"?
这样做是不起作用的,因为它会允许以引号开头但没有以引号结尾的模式。
"(pattern)"|(pattern)
这样可以运行,但是有些重复。是否有更好的方法来避免重复模式?
如何编写一个正则表达式来匹配一个可以包含引号的模式,但是如果有引号,则必须在开头和结尾处具有匹配的引号?
"?(pattern)"?
这样做是不起作用的,因为它会允许以引号开头但没有以引号结尾的模式。
"(pattern)"|(pattern)
这样可以运行,但是有些重复。是否有更好的方法来避免重复模式?
/^(")?(pattern)(?(1)\1|)$/
匹配:
不匹配:
这个正则表达式有点复杂。它首先查找可选的引号,并将其放入第一个回溯引用中(如果找到)。然后查找您的模式。然后使用条件语法来表示“如果再次找到回溯引用1,则匹配它,否则不匹配”。整个模式都被锚定,这意味着它需要单独出现在一行上,以便不会捕获未匹配的引号(否则,pattern
中的pattern"
将匹配)。
请注意,对于条件语法的支持因引擎而异,更冗长但重复的表达式将得到更广泛的支持(并且可能更容易理解)。
更新:这个正则表达式的简化版本是/^(")?(pattern)\1$/
,它不需要条件语法。当我最初测试时,使用的测试工具给了我一个错误的负面结果,导致我将其排除在外(糟糕!)。
我会保留使用条件语法的解决方案供后人和感兴趣的人参考,但这个更简单的版本在更多引擎中可能更容易使用(只使用了回溯引用这一功能,可能不受支持)。
^("?)pattern\1$
可以很好地工作。(@wuputah的删除答案没有起作用,因为它没有被锚定。而且@Tim,贪婪量词/原子组是不需要的。) - Alan Moore^("?)pattern\1$
得到了错误的结果,这也是我一开始尝试条件语句解决方案的原因...糟糕。 - Daniel Vandersluis(".+"|.+)
。确保第一个匹配项带引号,第二个不带引号。根据您使用的编程语言,您应该能够使用反向引用。例如:
(["'])(pattern)\1|^(pattern)$
这样,您要求要么没有引号,要么在两端使用相同的引号。
这应该可以使用递归正则表达式(需要更长时间才能正确)工作。与此同时:在Perl中,您可以构建一个自修改的正则表达式。我将其作为学术示例留下;-)
my @stuff = ( '"pattern"', 'pattern', 'pattern"', '"pattern' );
foreach (@stuff) {
print "$_ OK\n" if /^
(")?
\w+
(??{defined $1 ? '"' : ''})
$
/x
}
结果:
"pattern" OK
pattern OK
通常@Daniel Vandersluis的回答是可行的。然而,一些编译器如果可选组(“)为空,则无法识别它,因此它们无法检测到反向引用\1。
为了避免这个问题,更健壮的解决方案是:
/^("|)(pattern)\1$/
然后编译器将始终检测第一组。如果表达式中有一些前缀并且您想先捕获它,则可以修改此表达式:
/^(key)=("|)(value)\2$/