如何编写一个匹配可以包含引号的模式的正则表达式,但如果确实如此,则必须在开头和结尾有匹配的引号?
"?(pattern)"?
将不起作用,因为它将允许以引号开头但不以引号结尾的模式。
"(pattern)"|(pattern)
会起作用,但会重复。有没有更好的方法可以在不重复模式的情况下做到这一点?
如何编写一个匹配可以包含引号的模式的正则表达式,但如果确实如此,则必须在开头和结尾有匹配的引号?
"?(pattern)"?
将不起作用,因为它将允许以引号开头但不以引号结尾的模式。
"(pattern)"|(pattern)
会起作用,但会重复。有没有更好的方法可以在不重复模式的情况下做到这一点?
/^(")?(pattern)(?(1)\1|)$/
火柴:
不匹配:
然而,这种模式有些复杂。它首先查找可选引用,如果找到,则将其放入反向引用 1。然后它会搜索您的模式。然后它使用条件语法说“如果再次找到反向引用 1,则匹配它,否则不匹配”。整个模式是锚定的(这意味着它需要单独出现在一行上),这样不匹配的引号就不会被捕获(否则pattern
inpattern"
会匹配)。
请注意,对条件的支持因引擎而异,更冗长但重复的表达式将得到更广泛的支持(并且可能更容易理解)。
更新:这个正则表达式的一个更简单的版本是/^(")?(pattern)\1$/
,它不需要条件。当我最初测试这个时,我使用的测试仪给了我一个假阴性,这导致我打折扣(哎呀!)。
为了后代和兴趣,我将保留有条件的解决方案,但这是一个更简单的版本,更有可能在更广泛的引擎中工作(反向引用是此处使用的唯一可能不受支持的功能)。
这也很简单:(".+"|.+)
. 确保第一个匹配带引号,第二个不带引号。
根据您使用的语言,您应该能够使用反向引用。像这样,说:
(["'])(pattern)\1|^(pattern)$
这样,您要求要么没有引号,要么两端都使用相同的引号。
这应该适用于递归正则表达式(需要更长的时间才能正确)。同时:在Perl中,您可以构建一个自我修改的正则表达式。我将把它作为一个学术例子;-)
my @stuff = ( '"pattern"', 'pattern', 'pattern"', '"pattern' );
foreach (@stuff) {
print "$_ OK\n" if /^
(")?
\w+
(??{defined $1 ? '"' : ''})
$
/x
}
结果:
"pattern" OK
pattern OK