Почему мой не жадный регулярный выражения Perl ничего не соответствует? - PullRequest
4 голосов
/ 03 апреля 2009

Мне показалось, что я достаточно хорошо понял Perl RE, но это меня озадачивает:

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

my $test = "'some random string'";

if($test =~ /\'?(.*?)\'?/) {
       print "Captured $1\n";
       print "Matched $&";
}
else {
       print "What?!!";
}

отпечатки

Захваченные
Подходит '

Похоже, что он совпадает с окончанием "один, и поэтому ничего не захватил.
Я бы ожидал, что он будет соответствовать целиком, или, если он полностью не жадный, вообще ничего (поскольку все, что есть, может совпадать).
Это промежуточное поведение сбивает меня с толку, кто-нибудь может объяснить, что происходит?

Ответы [ 5 ]

14 голосов
/ 03 апреля 2009

\'? в начале и конце означает , совпадающие с 0 или 1 апострофами, жадно . (Как указал другой автор, чтобы сделать его не жадным, оно должно быть \'??)

.*? в середине означает совпадение с 0 или более символами без жадности .

Механизм регулярных выражений Perl просматривает первую часть строки. Он будет соответствовать началу, но делает это с жадностью, поэтому он подхватывает первый апостроф. Затем он сопоставляется без жадности (поэтому занимает как можно меньше), за которым следует необязательный апостроф. Это соответствует пустой строке.

3 голосов
/ 03 апреля 2009

Я думаю, вы имеете в виду что-то вроде:

/'(.*?)'/      // matches everything in single quotes

или

/'[^']*'/      // matches everything in single quotes, but faster

Одиночные кавычки не нужно избегать, АФАИК.

2 голосов
/ 03 апреля 2009

pattern? жадный, если вы хотите, чтобы он не был жадным, вы должны сказать pattern??:

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

my $test = "'some random string'";

if($test =~ /\'?(.*?)\'?/) {
       print "Captured [$1]\n";
       print "Matched  [$&]\n";
}
if($test =~ /\'??(.*?)\'??/) {
       print "Captured [$1]\n";
       print "Matched  [$&]\n";
}

от perldoc perlre:

Признаются следующие стандартные квантификаторы:

*      Match 0 or more times
+      Match 1 or more times
?      Match 1 or 0 times
{n}    Match exactly n times
{n,}   Match at least n times
{n,m}  Match at least n but not more than m times

По умолчанию квантифицированный подшаблон "жадный", то есть он будет соответствовать столько раз, сколько это возможно (учитывая конкретное начальное местоположение), в то время как все еще позволяя остальной части образца соответствовать. Если вы хотите это соответствует минимально возможное количество раз, следуйте квантификатору с "?" Обратите внимание, что значения не меняются, только «жадность»:

*?     Match 0 or more times
+?     Match 1 or more times
??     Match 0 or 1 time
{n}?   Match exactly n times
{n,}?  Match at least n times
{n,m}? Match at least n but not more than m times
1 голос
/ 16 апреля 2009

Я бы сказал, что ближайший ответ на то, что вы ищете, это

/'?([^']*)'?/

Так что "получите одинарную кавычку, если она есть", "получите что-нибудь и все, что не является одинарной кавычкой", "получите последнюю одинарную кавычку, если она есть".

Если вы не хотите совпадать с «не делайте этого» - но кто все равно использует апостроф в одинарной кавычке (и сходит с рук надолго)? :)

1 голос
/ 03 апреля 2009

Остерегайтесь делать все элементы вашего регулярного выражения необязательными (т. Е. Иметь все элементы количественно * или?). Это позволяет механизму регулярных выражений Perl сопоставлять столько, сколько ему нужно (даже ничего), но при этом считать совпадение успешным.

Я подозреваю, что вы хотите

/'(.*?)'/
...