【发布时间】:2013-07-10 22:43:56
【问题描述】:
给定 perl 中的正则表达式,我如何找到该正则表达式中捕获的最大组数?我知道我可以使用 $1、$2 等来引用第一个、第二个等捕获的组。但是如何找到此类组的最大数量?通过捕获的组,我的意思是括号中的正则表达式匹配的字符串。例如:如果正则表达式是 (a+)(b+)c+ 则字符串“abc”匹配该正则表达式。第一个捕获的组是 1 美元,第二个是 2 美元。
【问题讨论】:
给定 perl 中的正则表达式,我如何找到该正则表达式中捕获的最大组数?我知道我可以使用 $1、$2 等来引用第一个、第二个等捕获的组。但是如何找到此类组的最大数量?通过捕获的组,我的意思是括号中的正则表达式匹配的字符串。例如:如果正则表达式是 (a+)(b+)c+ 则字符串“abc”匹配该正则表达式。第一个捕获的组是 1 美元,第二个是 2 美元。
【问题讨论】:
amon 在提到%+ 哈希时暗示了这个问题的答案。但你需要的是@+ 数组:
@+
此数组保存当前活动动态范围内最后成功的子匹配的末端的偏移量。 $+[0] 是整个匹配结束的字符串的偏移量。这与在匹配的变量上调用 pos 函数返回的值相同。该数组的第 n 个元素保存第 n 个子匹配的偏移量,因此 $+1 是超过 $1 结束位置的偏移量,$+[2] 是超过 $2 结束位置的偏移量,依此类推。 您可以使用 $#+ 来确定上次成功匹配中有多少子组。请参阅为 @- 变量提供的示例。 [强调]
$re = "(.)" x 500;
$str = "a" x 500;
$str =~ /$re/;
print "Num captures is $#+"; # outputs "Num captures is 500"
【讨论】:
捕获的数量实际上是无限的。虽然您只能使用$1–$9 变量访问九个捕获,但您可以使用更多捕获组。
如果您有多个捕获组,您可能希望使用命名捕获,例如
my $str = "foobar";
if ($str =~ /(?<name>fo+)/) {
say $+{name};
}
输出:foo。您可以通过 %+ 哈希访问命名捕获的值。
【讨论】:
$10, $11, etc. 如果超过 9 个组也可以使用。
您可以使用如下代码来计算捕获组的数量:
$regex = qr/..../; # Some arbitrary regex with capture groups
my @capture = '' =~ /$regex|()/; # A successful match incorporating the regex
my $groups_in_my_regex = scalar(@capture) - 1;
它的工作方式是执行必须成功的匹配,然后检查创建了多少捕获组。 (由于尾随|()而创建了一个额外的@
编辑:实际上,似乎没有必要附加一个额外的捕获组。只要保证匹配成功,那么数组将包含每个捕获组的条目。
所以我们可以把第 2 行和第 3 行改成:
my @capture = '' =~ /$regex|/; # A successful match incorporating the regex
my $groups_in_my_regex = scalar(@capture);
【讨论】: