1

在 Perl 中,命名捕获组可用于使用正则表达式从字符串中提取数据:

perl -wle '
    use Data::Dumper;
    "abc" =~ / (?<B> (?<A> a ) b ) c /x and print "match!";
    print Dumper(\%+);
'

印刷

match!                                                                                                                            
$VAR1 = {                                                                                                                         
      'B' => 'ab',                                                                                                            
      'A' => 'a'                                                                                                              
    };                                                                                                                        

但是如何获得匹配项 A 和 B 在字符串中的位置"abc"?使用命名的捕获组时,可以引用正则表达式变量@-and @+,但这不适用于命名组 (*)。

(*) '不起作用'是指我不能使用捕获组的名称来检索位置,而只能使用组的编号(例如$-[1],对于组 A 的起始位置,但不是类似的东西$START_POS{A})。这减少了命名捕获组的使用,如果事先不知道捕获组的顺序,甚至可能无法使用。

4

1 回答 1

1

可以参考正则表达式变量@-and @+,但这不适用于命名组。

让我们首先建立它@+并按@-预期工作:

perl -wle '
    use Data::Dumper;
    "abc" =~ / (?<B> (?<A> a ) b ) c /x and print "match!";
    print Dumper(\@+);'
match!
$VAR1 = [
          3,
          2,
          1
        ];

perl -wle '
    use Data::Dumper;
    "abc" =~ / (?<B> (?<A> a ) b ) c /x and print "match!";
    print Dumper(\@-);'
match!
$VAR1 = [
          0,
          0,
          0
        ];

现在,由于我发布了上述内容,您已经通过以下方式扩展了您的问题

(*) '不起作用'是指我不能使用捕获组的名称来检索位置,而只能使用组的编号(例如$-[1],对于 group 的起始位置A,但不是类似的东西$START_POS{A})。这减少了命名捕获组的使用,如果事先不知道捕获组的顺序,甚至可能无法使用。(强调我的)

我不太明白你的意思或你为什么需要这个,但我反复的询问仍未得到答复,所以这是你字面问题的答案。

查看perldoc perlvar,我们注意到目前没有机制可以让您通过捕获组的名称查找匹配位置的另一个散列。

%LAST_PAREN_MATCH %+

与 类似@+%+哈希允许访问命名的捕获缓冲区,如果它们存在,则在当前活动动态范围内的最后一次成功匹配中。

例如,$+{foo}在以下匹配之后等价于 $1:

   'foo' =~ /(?<foo>foo)/;

哈希列表的键%+仅包含已捕获的缓冲区的名称(因此与定义的值相关联)。

的底层行为%+Tie::Hash::NamedCapture模块提供。... 这个变量是在 Perl v5.10.0 中添加的。此变量是只读的并且是动态范围的。

在比赛之后建立这样一个查找表实际上相当简单,但正如我之前提到的,我不确定你为什么需要它,而且它似乎不是我之前遇到的任何问题的最佳解决方案。它可能不是最适合您的问题的解决方案,因此您最好解释一下您实际尝试解决的问题。

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my $str = 'abc';

$str =~ / (?<B> (?<A> a) b) c /x;

my %captured_to_pos = map +(substr($str, $-[$_], $+[$_] - $-[$_]) => [$-[$_], $+[$_]]), 0 .. $#+;

print Dumper $captured_to_pos{$+{$_}} for qw( A B );

输出:

$VAR1 = [
          0,
          1
        ];
$VAR1 = [
          0,
          2
        ];

如果不同的捕获组可以匹配相同的字符串,则您必须更加小心,但是如果没有您提供足够的激励性解释,我认为没有理由深入研究。

于 2017-05-22T13:26:13.363 回答