Максимальное количество захваченных групп в регулярном выражении Perl
Учитывая регулярное выражение в Perl, как мне найти максимальное количество захваченных групп в этом регулярном выражении? Я знаю, что могу использовать $1, $2 и т. Д. Для ссылки на первую, вторую и т. Д. Захваченные группы. Но как мне найти максимальное количество таких групп? Под захваченными группами я подразумеваю строку, совпадающую с регулярным выражением в парантезе. Например: если регулярное выражение равно (a+)(b+)c+, то строка "abc" соответствует этому регулярному выражению. И первая захваченная группа будет 1 доллар, вторая будет 2 доллара.
3 ответа
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
, Вы можете получить доступ к значениям именованных захватов через %+
хэш.
Вы можете использовать код, подобный следующему, чтобы подсчитать количество групп захвата:
$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);
Смотрите также:
Считать группы захвата в регулярном выражении qr?