3

可以强制 Perl 5 正则表达式匹配最长可能的字符串,如果正则表达式是,例如:

a|aa|aaa

我发现在 perl 6 中可能是默认设置,但在 perl 5 中,我怎样才能得到这种行为?

示例模式:

[0-9]|[0-9][0-9]|[0-9][0-9][0-9][0-9]

如果我有 string 2.10.2014,那么第一个匹配将是 2,这没关系;但下一场比赛将是 1,这是不行的,因为它应该是 10。然后 2014 将是 4 随后匹配 2,0,1,4,但它应该是 2014 使用 [0-9][0-9] [0-9][0-9]。我知道我可以使用 [0-9]+,但我不能。

4

4 回答 4

4

一般解决方案:将最长的放在第一位。

my ($longest) = /(aaa|aa|a)/

具体解决方案:使用

my ($longest) = /([0-9]{4}|[0-9]{1,2})/

如果您无法编辑模式,则必须找到所有可能性并找到其中最长的一个。

my $longest;
while (/([0-9]|[0-9][0-9]|[0-9][0-9][0-9][0-9])/g) {
   $longest = $1 if length($1) > length($longest);
}
于 2013-02-23T01:53:26.920 回答
2

对于未知模式,我能看到的最明智的解决方案是匹配所有可能的模式,查看匹配子串的长度并选择最长的子串:

my @patterns = (qr/a/, qr/a(a)/, qr/b/, qr/aaa/);
my $string = "aaa";

my @substrings = map {$string =~ /($_)/; $1 // ()} @patterns;

say "Matched these substrings:";
say for @substrings;

my $longest_token = (sort { length $b <=> length $a } @substrings)[0];

say "Longest token was: $longest_token";

输出:

Matched these substrings:
a
aa
aaa
Longest token was: aaa

对于已知模式,可以手动对它们进行排序,以便第一次匹配与最长匹配相同:

"aaa" =~ /(aaa|aa|b|a)/;
say "I know that this was the longest substring: $1";
于 2013-02-23T01:57:30.583 回答
2

替代将使用匹配的第一个替代,因此只需编写即可/aaa|aa|a/

对于您在问题中显示的示例,只需将最长的替代项放在第一位,就像我说的那样:

[0-9][0-9][0-9][0-9]|[0-9][0-9]|[0-9]
于 2013-02-23T01:18:04.397 回答
-1
perl -Mstrict -Mre=/xp -MData::Dumper -wE'
  {package Data::Dumper;our($Indent,$Sortkeys,$Terse,$Useqq)=(1)x4}
  sub _dump { Dumper(shift) =~ s{(\[.*?\])}{$1=~s/\s+/ /gr}srge }
  my ($count, %RS);
  my $s= "aaaabbaaaaabbab";
  $s =~ m{ \G a+b? (?{ $RS{ $+[0] - $-[0] } //= [ ${^MATCH}, $-[0] ]; $count++ }) (*FAIL) };
  say sprintf "RS: %s", _dump(\%RS);
  say sprintf "count: %s", $count;
'
RS: {
  "1" => [ "a", 0 ],
  "2" => [ "aa", 0 ],
  "3" => [ "aaa", 0 ],
  "4" => [ "aaaa", 0 ],
  "5" => [ "aaaab", 0 ]
}

count: 5
于 2017-05-05T16:39:15.333 回答