Почему в этой ситуации perl не сохраняет переменную match?

Я просто долго пытался придумать работающую маленькую однострочную строчку на Perl, подобную этой:

perl -pe 'if (/^(".*",").*, /) { $a = $1; s/, /"\n$a/g}'

Мои входные данные выглядят примерно так:

"foo","bar a"
"baz","bar a, bar b, bar c"

И я преобразовываю это в это:

"foo","bar a"
"baz","bar a"
"baz","bar b"
"baz","bar c"

По сути, я хотел сопоставить только определенные строки (if (/, /)...) и в этих строках заменить все экземпляры этого совпадения частью исходной строки. s///g с группой соответствия не будет работать, потому что она не будет рекурсивно правильно, строка замены должна быть вычислена до того, как замены начнут происходить.

if (/^(".*",").*, /) { s/, /"\n$1/g}

Но это не так. Переменная $1 всегда была пустой. Учитывая то, что написано в документах о сохраняемости, я сюрприз для меня:

Эти переменные соответствия обычно остаются до следующего успешного сопоставления с образцом.

Только когда я начал хранить результат в собственной переменной, я смог получить доступ к результату из выражения подстановки:

if (/^(".*",").*, /) { $a = $1; s/, /"\n$a/g}

Почему $1 очищался, когда не было не только успешного совпадения, но и вообще не было запроса на совпадение в моем поиске и замене? И был ли лучший способ подойти к этой проблеме?


person Caleb    schedule 16.07.2019    source источник


Ответы (2)


Ты спрашиваешь:

Почему был очищен $1, если не было не только успешного совпадения, но и вообще не было запроса на совпадение в моем поиске и замене?

Возможно, вы путаете сопоставление и захват?

Чтобы s/PATTERN/REPLACEMENT/ что-то сделал, ШАБЛОН должен совпадать. Таким образом, если в результате операции s/// есть какая-либо замена, вы знаете, что ее регулярное выражение PATTERN успешно сопоставлено. Затем оценивается REPLACEMENT.

(В вашем случае s/, /.../ ШАБЛОН совпадает хотя бы один раз с запятой и пробелом после текста bar a во второй строке ввода.)

Конечно, когда это произойдет, интерпретатор сбросит все элементы захвата ($1, $2 и т. д.) на любой захваченный ШАБЛОН. Опять же, это до оценки REPLACEMENT. Поскольку ваш ШАБЛОН ничего не захватывает, эти элементы не определены, как если бы вы явно выполнили не захватывающее m/, / совпадение.

person pilcrow    schedule 16.07.2019

Значения переменных сопоставления действительно сохраняются до следующего успешного совпадения с шаблоном (или до тех пор, пока не будет закрыта область, в которой произошло совпадение).

В вашем случае они изменились из-за успешного совпадения с образцом. Вы успешно сопоставили шаблон , . Таким образом, переменные захвата будут отражать текст, захваченный захватами этого совпадения. $1 возвращает текст, соответствующий несуществующему первому захвату, поэтому он вернул undef.

$ perl -e'
   $_ = "a";
   s/(a)/a/;  CORE::say $1 // "[undef]";  # Successful match
   s/(c)/c/;  CORE::say $1 // "[undef]";  # Unsuccessful match
   s/a/a/;    CORE::say $1 // "[undef]";  # Successful match
'
a
a
undef
person ikegami    schedule 16.07.2019
comment
Вы не читаете весь вопрос. Документация, которую я читал, предполагает, что переменные захвата устанавливаются только при УСПЕШНОМ совпадении и могут зависать с предыдущих совпадений. Поскольку у меня не было групп совпадений в выражении, я был удивлен, что предыдущее значение сдулось. - person Caleb; 16.07.2019
comment
Re Документация, которую я читал, предполагает, что переменные захвата устанавливаются только при УСПЕШНОМ совпадении, это правильно. И, как говорится и показывает мой ответ, матч был успешным. - person ikegami; 16.07.2019
comment
Re Поскольку у меня не было групп соответствия в выражении, я был удивлен, что предыдущее значение сдулось. Как вы сами заявили, решающим фактором является не наличие групп захвата или нет, а наличие был удачный матч или нет - person ikegami; 16.07.2019
comment
Ваш ответ демонстрирует соответствие группе захвата. В моем примере даже нет группы захвата для успешного или неудачного сопоставления. - person Caleb; 16.07.2019
comment
Re В моем примере даже нет группы захвата для успешного или неудачного сопоставления. Не имеет значения. Как я уже продемонстрировал, все еще имело место успешное совпадение с образцом. Тем не менее, я заменил пример. - person ikegami; 16.07.2019