在Perl的正则表达式

时间:2017-05-22 13:12:19

标签: regex perl capture-group

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

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

打印

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

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

(*)&#39;不起作用&#39;我的意思是我不能使用捕获组的名称来检索位置,而只使用组的编号(例如,{A}的起始位置$-[1],但不是$START_POS{A}。这会重新使用命名的捕获组,如果不提前知道捕获组的顺序,甚至可能无法使用。

1 个答案:

答案 0 :(得分:0)

  

可以引用正则表达式变量@-@+,但这对命名组不起作用。

让我们首先确定@+@-按预期工作:

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
        ];

现在,由于我发布了上述内容,您已经通过说

扩展了您的问题
  

(*)&#39;不起作用&#39;我的意思是我不能使用捕获组的名称来检索位置,而只使用组的编号(例如$-[1]作为组A的起始位置,但不是{{1} }})。 这会重新使用命名捕获组,如果不提前知道捕获组的顺序,甚至可能无法使用。(强调我的)

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

关注perldoc perlvar,我们注意到目前没有机制可以使用另一个哈希,它允许您按捕获组的名称查找匹配位置。

  

<强> $START_POS{A}   的 %LAST_PAREN_MATCH

     

%+类似,@+哈希允许在当前活动动态范围的最后一次成功匹配中访问指定的捕获缓冲区(如果存在)。

     

例如,%+在以下匹配后相当于$ 1:

$+{foo}
     

'foo' =~ /(?<foo>foo)/; 哈希的键仅列出已捕获的缓冲区的名称(因此与定义的值相关联)。

     

%+模块提供%+的基本行为。   ...   在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
        ];

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