如何将模式与可选的周围引号相匹配?

问题描述 投票:0回答:6

如何编写一个正则表达式来匹配可以包含引号的模式,但如果包含引号,则必须在开头和结尾具有匹配的引号?

"?(pattern)"?

不起作用,因为它将允许以引号开头但不以引号结尾的模式。

"(pattern)"|(pattern)

可以工作,但有重复性。有没有更好的方法来做到这一点而不重复模式?

regex quotations repeat surround
6个回答
28
投票

您可以通过使用 backreferencesconditionals 获得无需重复的解决方案:

/^(")?(pattern)(?(1)\1|)$/

比赛:

  • 图案
  • “模式”

不匹配:

  • ”图案
  • 图案”

然而,这种模式有些复杂。它首先查找可选引用,如果找到,则将其放入反向引用 1 中。然后它会搜索您的模式。然后它使用条件语法来表示“如果再次找到反向引用 1,则匹配它,否则不匹配”。整个模式是anchored(这意味着它需要单独出现在一行上),这样不匹配的引号就不会被捕获(否则

pattern
中的
pattern"
会匹配)。

请注意,对条件的支持因引擎而异,更详细但重复的表达式将得到更广泛的支持(并且可能更容易理解)。


更新: 这个正则表达式的一个更简单的版本是

/^(")?(pattern)\1$/
,它不需要条件。当我最初测试这个时,我使用的测试仪给了我一个假阴性,这导致我对它打折扣(哎呀!)。

为了后代和兴趣,我将保留带有条件的解决方案,但这是一个更简单的版本,更有可能在更广泛的引擎中工作(反向引用是此处使用的唯一可能不受支持的功能)。


2
投票

这也很简单:

(".+"|.+)
。确保第一个匹配项带引号,第二个匹配项不带引号。


1
投票

根据您使用的语言,您应该能够使用反向引用。像这样,说:

(["'])(pattern)\1|^(pattern)$

这样,您就需要要么没有引号,要么两端使用相同的引号。


0
投票

这应该与递归正则表达式一起使用(需要更长的时间才能正确)。同时:在Perl中,您可以构建一个自修改正则表达式。我将把它作为一个学术例子;-)

my @stuff = ( '"pattern"', 'pattern', 'pattern"', '"pattern'  );

foreach (@stuff) {
   print "$_ OK\n" if /^
                        (")?
                        \w+
                        (??{defined $1 ? '"' : ''})
                       $
                      /x
}

结果:

"pattern" OK
pattern OK

0
投票

一般来说@Daniel Vandersluis的回复会起作用。但是,如果可选组 (") 为空,某些编译器将无法识别该组,因此它们不会检测反向引用。

为了避免这个问题,更稳健的解决方案是:

/^("|)(pattern)\1$/

那么编译器将始终检测第一组。如果表达式中有一些前缀并且您想先捕获它,也可以修改此表达式:

/^(key)=("|)(value)\2$/

0
投票

对于支持

?P<name>
命名组语法的正则表达式,以下 Python
re
示例说明了如何使用它来确保结束引号与可选的开始引号匹配:

 re.compile(r"""^
            (?P<quote>['"]?)                  # optional quote
            (?P<sha1>([0-9-a-f]{40}))\s+      # SHA-1 of commit-id
            # ...
            (?P=quote)$""",                   # match opening quote if it exists
            re.VERBOSE)

注意末尾的

?P=quote
,它引用了开头的命名模式。这可确保
blah
'blah'
"blah"
全部匹配,但
'blah"
不匹配。

在 Perl 中也可以完成同样的操作,但它对

(?P=NAME)
的支持不允许使用单引号作为分隔符。所以

echo \"blah\" | perl -ne 'm/(?P<quote>["x]?)(\w+)(?P=quote)/ and print $2;'

可以工作,但为了支持单引号,必须使用

\k{NAME}
来反向引用。参见曼·佩尔雷(1).

© www.soinside.com 2019 - 2024. All rights reserved.