Когда \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, так что не получается.

Другие вопросы по тегам