匹配Perl中第n个可能的最长字符串

ali*_*nia 5 regex string perl pattern-matching

Perl正则表达式的模式匹配量词是"贪婪的"(它们匹配最长的可能字符串).为了迫使比赛"不合适",一个?可以附加到模式量词(*,+).

这是一个例子:

#!/usr/bin/perl

$string="111s11111s";

#-- greedy match
$string =~ /^(.*)s/;
print "$1\n"; # prints 111s11111

#-- ungreedy match
$string =~ /^(.*?)s/;
print "$1\n"; # prints 111
Run Code Online (Sandbox Code Playgroud)

但是如何在Perl中找到第二,第三和......可能的字符串匹配?举一个你的简单例子 - 如果需要更好的一个.

Mil*_*ler 10

利用条件表达式,代码表达式回溯控制动词.

my $skips = 1;
$string =~ /^(.*)s(?(?{$skips-- > 0})(*FAIL))/;
Run Code Online (Sandbox Code Playgroud)

以上将使用贪婪匹配,但会导致最大匹配故意失败.如果你想要第三大,你可以设置跳过的数量为2.

演示如下:

#!/usr/bin/perl
use strict;
use warnings;

my $string = "111s11111s11111s";

$string =~ /^(.*)s/;
print "Greedy match     - $1\n";

$string =~ /^(.*?)s/;
print "Ungreedy match   - $1\n";

my $skips = 1;
$string =~ /^(.*)s(?(?{$skips-- > 0})(*FAIL))/;
print "2nd Greedy match - $1\n";
Run Code Online (Sandbox Code Playgroud)

输出:

Greedy match     - 111s11111s11111
Ungreedy match   - 111
2nd Greedy match - 111s11111
Run Code Online (Sandbox Code Playgroud)

使用此类高级功能时,必须充分了解正则表达式以预测结果.这种特殊情况有效,因为正则表达式是固定在一端的^.这意味着我们知道每个后续匹配也比前一个短.但是,如果两端都可能发生变化,我们无法预测秩序.

如果是这种情况,那么你找到它们,然后你对它们进行排序:

use strict;
use warnings;

my $string = "111s11111s";

my @seqs;
$string =~ /^(.*)s(?{push @seqs, $1})(*FAIL)/;

my @sorted = sort {length $b <=> length $a} @seqs;

use Data::Dump;
dd @sorted;
Run Code Online (Sandbox Code Playgroud)

输出:

("111s11111s11111", "111s11111", 111)
Run Code Online (Sandbox Code Playgroud)

注意Perl之前的版本 v5.18

Perl v5.18引入了一个更改,/(?{})/并且/(??{})/已经过大量重写,使得词法变量的范围能够在上面使用的代码表达式中正常工作.在此之前,上面的代码会导致以下错误,如在v5.16.2下运行的子例程版本中所示:

Variable "$skips" will not stay shared at (re_eval 1) line 1.
Variable "@seqs" will not stay shared at (re_eval 2) line 1.
Run Code Online (Sandbox Code Playgroud)

RE代码表达式的旧实现的修复是在初始化时使用our,以及进一步良好的编码实践来声明变量localize.这在v5.16.2下运行的这个修改过的子程序版本中得到了证明,或者如下所示:

local our @seqs;
$string =~ /^(.*)s(?{push @seqs, $1})(*FAIL)/;
Run Code Online (Sandbox Code Playgroud)

  • @Miller:实际上,没有.这已经多次讨论过(参见[1](http://meta.stackexchange.com/questions/135112),[2](http://meta.stackexchange.com/q/176902/220538),[ 3](http://meta.stackoverflow.com/a/254995/1438393)).使用内联代码格式化强调一直是不受欢迎的; 这就是大胆和斜体的含义. (4认同)