禁止在已编译的正则表达式中捕获? (例如,Perl 5.22 +,/ n修饰符)

时间:2018-09-16 19:20:39

标签: regex perl regex-lookarounds regex-group

环境: Cygwin x64上的Perl 5.26.2 x64。

问题:在my $re = qr/...(capturing group).../之后,有什么方法可以使用$re而不捕获到其捕获组中?

X:我正在匹配的行可能是:

#define FOO(X,Y) SomeComplicatedStuff

#define FOO(X,Y) BAR(X,Y)

我有一个已编译的正则表达式$re,它与FOO(X,Y)匹配,并包括编号的捕获组,以将匹配项分为FOOX,Y。我想匹配第二种形式的行而不必定义单独的正则表达式,例如,使用m/$re.+$re/。效果很好,但是当我真正想要的是FOO的组时,我得到了BAR的所有捕获组。

Y:我以为我可以在5.22+中使用/n修饰符来执行此操作,但是我无法使其正常工作。 MCVE:

$ perl -E 'my $re=qr/(foo|bar)/; "foobar" =~ m/$re$re/; say $1, " ", $2;'
foo bar     # as expected

$ perl -E 'my $re=qr/(foo|bar)/; "foobar" =~ m/(?n:$re)$re/; say $1, " ", $2;'
            # I think this should turn off      ^^^  capturing of `foo`
foo bar     # oops - I was hoping for `bar`

$ perl -E 'my $re=qr/(foo|bar)/; "foobar" =~ m/(?n:(foo|bar))$re/; say $1, " ", $2;'
bar         # This works, but I had to inline $re within (?n:...).

注意:我也尝试过\K

$ perl -E 'my $re=qr/(foo|bar)/; "foobar" =~ m/$re\K$re/; say $1, " ", $2, " ", $&;'
foo bar bar      # was hoping for `bar  bar`

编辑-忘了提一下-我确实看过this related question,但这不是相同的问题说明。

2 个答案:

答案 0 :(得分:3)

$re的字符串化为(?^u:(foo|bar))。换句话说,它将标志设置为编译模式时使用的标志,从而关闭/n

您可以使用以下任何一种方式:

my $re = qq/(foo|bar)/;    # Note: Gotta escape `\` that are part of regex escapes.
/(?n:$re)$re/

(转义的示例:使用此技术时,qr{(fo\w|ba\w)}变为qq{(fo\\w|ba\\w)}。)

my $re = qr/foo|bar/;
/$re($re)/

my $re = qr/
   (?<foo_or_bar>) ((?<foo_or_bar>))
   (?(DEFINE)
      (?<foo_or_bar>foo|bar)
   )
/x;
/$re/

答案 1 :(得分:2)

好吧,我找到了解决方法,但这当然不是答案!无论如何,我都会在这里发布,以防其他人使用。在我的特定用例中,匹配项分为两部分。因此,在第一场比赛中使用/g,在第二场比赛中使用\G可以解决问题。示例:

$ perl -E '
    my $re=qr/(foo|bar)/;
    my $str = "foo bar";

    $str =~ m/$re/g;         # Match `foo`, and set `pos` (because of /g)
    say "Expecting foo: ", $1;

    $str =~ m/\G.+$re/g;     # \G => skip past `foo`, and check ` bar` against `.+$re`
    say "Hoping for bar: ";
'
Expecting foo: foo
Hoping for bar: bar          # Hooray!