Когда \G является полезным приложением в регулярных выражениях?
Я не уверен в использовании / необходимости \G
оператор.
Я прочитал в perldoc:
Якорь \G используется для начала следующего совпадения в той же строке, где было остановлено последнее совпадение.
Я не очень понимаю это утверждение. Когда мы используем \g
мы обычно переходим к персонажу после последнего матча в любом случае.
Как показывает пример:
$_ = "1122a44";
my @pairs = m/(\d\d)/g; # qw( 11 22 44 )
Тогда это говорит:
Если вы используете якорь \G, вы заставляете совпадение после 22 начинать с a:
$_ = "1122a44";
my @pairs = m/\G(\d\d)/g;
Регулярное выражение не может соответствовать там, так как оно не находит цифру, поэтому следующее совпадение завершается неудачно, и оператор соответствия возвращает пары, которые он уже нашел
Я тоже этого не понимаю. "Если вы используете якорь \G, вы заставляете совпадение после 22 начинаться с." Но без \G будет предпринята попытка сопоставления a
в любом случае верно? Так в чем же смысл этого предложения?
Я вижу, что в этом примере единственными напечатанными парами являются 11 и 22. Таким образом, 44 не пробовал.
Пример также показывает, что с помощью c
опция делает это индексом 44 через некоторое время.
Если честно, из всего этого я не могу понять, в чем полезность этого оператора и когда его следует применять.
Может кто-нибудь, пожалуйста, помогите мне понять это, возможно, на содержательном примере?
Обновить
Я думаю, что я не понял это ключевое предложение:
Если вы используете якорь \G, вы начинаете совпадение после 22, чтобы начать с a. Регулярное выражение не может соответствовать там, так как оно не находит цифру, поэтому следующее совпадение завершается неудачно, и оператор соответствия возвращает пары, которые он уже нашел.
Похоже, это означает, что когда совпадение не удается, регулярное выражение не предпринимает дальнейших попыток и согласуется с примерами в ответах.
Также:
После неудачного совпадения буквы a, perl сбрасывает pos() и начинается следующее совпадение в той же строке.
3 ответа
\G является якорем; это указывает, где матч должен начаться. Когда присутствует \G, он не может начать сопоставление с какой-либо произвольной более поздней точки в строке; когда \G отсутствует, он может.
Это наиболее полезно при разборе строки на отдельные части, где вы не хотите пропускать другие вещи. Например:
my $string = " a 1 # ";
while () {
if ( $string =~ /\G\s+/gc ) {
print "whitespace\n";
}
elsif ( $string =~ /\G[0-9]+/gc ) {
print "integer\n";
}
elsif ( $string =~ /\G\w+/gc ) {
print "word\n";
}
else {
print "done\n";
last;
}
}
Вывод с \G's:
whitespace
word
whitespace
integer
whitespace
done
без:
whitespace
whitespace
whitespace
whitespace
done
Обратите внимание, что я демонстрирую использование сопоставления скалярного контекста /g, но \G в равной степени применяется к сопоставлению контекста списка /g, и на самом деле вышеприведенный код легко модифицируется, чтобы использовать это:
my $string = " a 1 # ";
my @matches = $string =~ /\G(?:(\s+)|([0-9]+)|(\w+))/g;
while ( my ($whitespace, $integer, $word) = splice @matches, 0, 3 ) {
if ( defined $whitespace ) {
print "whitespace\n";
}
elsif ( defined $integer ) {
print "integer\n";
}
elsif ( defined $word ) {
print "word\n";
}
}
Но без \G сопоставление будет предпринято в любом случае, верно?
Без \G
, он не будет ограничен, чтобы начать сопоставление там. Он попробует, но попробует начать позже, если потребуется. Вы можете думать о каждом шаблоне как о подразумеваемом \G.*?
впереди.
Добавить \G
и смысл становится очевидным.
$_ = "1122a44";
my @pairs = m/\G (\d\d)/xg; # qw( 11 22 )
my @pairs = m/\G .*? (\d\d)/xg; # qw( 11 22 44 )
my @pairs = m/ (\d\d)/xg; # qw( 11 22 44 )
Если честно, из всего этого я не могу понять, в чем полезность этого оператора и когда его следует применять.
Как видите, вы получите разные результаты, добавив \G
Таким образом, полезность получает желаемый результат.
Интересные ответы и много верны, я думаю, но я также могу предположить, что это все еще не объясняет много.
\ G 'заставляет' следующий матч происходить в позиции, где последний матч закончился.
В принципе:
$str="1122a44";
while($str=~m/\G(\d\d)/g) {
#code
}
Первое совпадение = "11" Второе совпадение принудительно начинается с 22, и да, это \ d \ d, поэтому результат равен "22". Третья попытка принудительно начинается с "а", но это не \ d \ d, так что не получается.