Мнимый символ \G означает позицию конца предыдущего совпадения. Это аналог функции pos, но только внутри регулярного выражения. Этот метасимвол впервые появился в Perl для проведения глобального поиска и замены. Он совпадает с позицией, в которой закончилась предыдущая итерация поиска с модификатором g. Свое значение этот якорь хранит также и после окончания работы оператора поиска/замены, как и функция pos. При первой итерации поиска/замены или после сброса текущей позиции поиска в начало текста \G совпадает в начале текста как и метасимвол \A. При принудительной переустановке текущей позиции поиска при обращении к функции pos это якорь соответствует установленной позиции. Рассмотрим примеры, которые показывают, как работает якорь \G и чем он может быть полезен.
Мы уже рассматривали примеры поиска в скалярном контексте с модификатором g. При обращению к другому или тому же оператору с модификатором g и той же переменной с целевым текстом отыскивается следующее совпадение. Но оно ищется без привязки к концу предыдущего совпадния и может быть найдено с любой позиции после конца предыдущего совпадения. Иногда бывает нужно, чтобы следующий поиск был привязан к концу последнего совпадения и чтобы поиск заканчивался неудачей, если поиск следующего образца начинается не с этой начальной позиции. Это аналогично привязке к началу текста \A.
Например, мы ищем слова, разделенные вертикальной чертой:
$_='|ab|cd |ef'; while (/\|(\w+)/g) { print "$1\n" }
Этот пример выведет
ab cd ef
А теперь потребуем, чтобы слова были разделены лишь одной вертикальной чертой. Вот здесь и нужна эта привязка \G к концу предыдущего совпадения:
$_='|ab|cd |ef'; while (/\G\|(\w+)/g) { print "$1\n" }
В результате получаем:
ab cd
Якорь \G надежно работает, если он стоит в самом начале регулярного выражения, которое не имеет высокоуровневой конструкции выбора альтернативы. Если такая конструкция имеется, то якорь \G надо выносить за скобки:
/\G(?: шаблон1 | шаблон2 | … )/
Если этот мнимый символ стоит где-либо в другом месте, то правильная его работа не гарантируется, во всяком случае, это приведет к сильному замедлению в работе регулярного выражения.
Теперь поясню, чем же отличается конец предыдущего совпадения от начала текущего совпадения. Неужели это не одно и то же? Если совпадение было с непустным фрагментом текста, то это то же самое. Но если совпадение было с "пустотой", то, как мы уже знаем, механизм регулярных выражений принудительно передвигает текущую позицию поиска на один символ, чтобы избежать зацикливания. Рассмотрим такие примеры:
$_='abcd'; s/z*/!/g; print $_;