12

我一直在研究perldoc perlre正则表达式食谱和 Stack Overflow 上的相关问题,我似乎找不到看起来非常有用的表达式:我怎么知道当前匹配的数量?

有最后一个封闭组匹配的表达式($^N),匹配 3 的内容(\g{3}如果我理解正确的文档)$'$&$`。但似乎没有一个我可以使用的变量来简单地告诉我当前匹配的数量是多少。

真的失踪了吗?如果是这样,是否有任何解释的技术原因为什么很难实施,或者我只是没有足够仔细地阅读 perldoc?

请注意,我对内置变量感兴趣,而不是像使用(${$count++}).

对于上下文,我正在尝试构建一个仅匹配某些匹配实例的正则表达式(例如,匹配所有出现的字符“E”但不匹配出现的 3、7 和 10,其中 3、7 和 10 只是数字在一个数组中)。当我试图为这个 SO question构建一个更惯用的答案时,我遇到了这个问题。

我想避免将正则表达式作为字符串来实际将 3、7 和 10 插入到正则表达式本身中。

4

2 回答 2

6

我完全忽略了将其用于另一个问题的实际效用或智慧。

我想@-或者@+可能会做你想做的事,因为它们保存了编号匹配的偏移量,但看起来正则表达式引擎已经知道最后一个索引是什么:

use v5.14;

use Data::Printer;

$_ = 'abc123abc345abc765abc987abc123';

my @matches = m/
    ([0-9]+)
    (?{ 
        print 'Matched \$' . $#+ . " group with $^N\n";
        say p(@+);
    })
    .*?
    ([0-9]+)
    (?{ 
        print 'Matched \$' . $#+ . " group with $^N\n"; 
        say p(@+);
    })  
    /x;

say "Matches: @matches";

这给出了将最后一个索引显示为 2 的字符串,即使它尚未匹配$2

Matched \$2 group with 123
[
    [0] 6,
    [1] 6,
    [2] undef
]
Matched \$2 group with 345
[
    [0] 12,
    [1] 6,
    [2] 12
]
Matches: 123 345

请注意,第一次$+[2]是 undef,因此尚未填写。你也许可以用它做点什么,但我认为这可能偏离了你的问题的精神。如果你真的很喜欢,你可以创建一个绑定的标量,它的值是最后定义的索引 in @+,我猜。

于 2012-08-12T00:25:42.427 回答
5

我玩了一会儿。同样,我知道这并不是您真正想要的,但我认为它不会以您想要的方式存在。

我有两个想法。首先,通过使用分隔符保留模式进行拆分,您可以将间隙位作为输出列表中的奇数元素。使用split中的列表,您可以计算您所在的匹配项,然后按照您的喜好将其重新组合在一起:

use v5.14;

$_ = 'ab1cdef2gh3ij4k5lmn6op7qr8stu9vw10xyz';

my @bits = split /(\d+)/; # separator retention mode

my @skips = qw(3 7 10);
my $s;
while( my( $index, $value ) = each @bits ) {
    # shift indices to match number ( index = 2 n - 1 )
    if( $index % 2 and ! ( ( $index + 1 )/2 ~~ @skips ) ) {
        $s .= '^';
        }
    else {
        $s .= $value;
        }
    }

我得到:

ab^cdef^gh3ij^k^lmn^op7qr^stu^vw10xyz

我以为我真的很喜欢我的分裂答案,直到我有了第二个想法。状态是否在替换中起作用?看来确实如此:

use v5.14;
$_ = 'ab1cdef2gh3ij4k5lmn6op7qr8stu9vw10xyz';
my @skips = qw(3 7 10);

s/(\d+)/
    state $n = 0;
    $n++;
    $n ~~ @skips ? $1 : '$'
    /eg;

say;

这给了我:

    ab$cdef$gh3ij$k$lmn$op7qr$stu$vw10xyz

我不认为你能比这更简单,即使那个魔法变量存在。

我有第三个想法,但我没有尝试。我想知道状态是否在代码断言中起作用。可能,但是我必须弄清楚如何使用其中一个来使匹配失败,这实际上意味着它必须跳过可能匹配的位。这看起来真的很复杂,这可能是 Borodin 甚至在伪代码中迫使你展示的东西。

于 2012-08-13T11:39:20.450 回答