Как заменить символ в совпавшем шаблоне с помощью амперсанда (&)

Когда мы сопоставляем шаблон с помощью sed, сопоставленный шаблон сохраняется в переменной «амперсанд» (&). Есть ли способ заменить символ в этом сопоставленном шаблоне, используя сам амперсанд?

Например, если & содержит строку «apple1», как я могу использовать &, чтобы преобразовать строку в «apple2» (т.е. заменить 1 на 2)?


person user1418321    schedule 02.10.2012    source источник
comment
Это не то, как вы используете &. Было бы полезно, если бы вы объяснили, почему вы хотите это сделать.   -  person nneonneo    schedule 02.10.2012


Ответы (4)


Если я правильно угадал, то вы хотите применить подстановку в соответствии с шаблоном. Вы не можете сделать это, используя &. Вместо этого вы хотите сделать это:

echo apple1 apple3 apple1 apple2 botemo1 | sed '/apple./ { s/apple1/apple2/g; }'

Это означает, что вы хотите выполнить подстановку команд только в строках, соответствующих шаблону /apple./.

person Elias Dorneles    schedule 02.10.2012
comment
Пожалуйста, объясните такому давнему новичку, как я, почему это лучше, чем sed 's/apple1/apple2/g'. Потому что я хочу использовать sed '/apple./ { s/1/2/g; }' , а он меняет его на botemo2, что совершенно нелогично. - person Steven Lu; 06.02.2016
comment
@StevenLu Вещь sed ориентирована на строки, поэтому /apple./ означает: применять команды для выполнения только к строкам, которые соответствуют шаблону. Поскольку botemo1 находится в той же строке, sed также применит замену для него. - person Elias Dorneles; 06.02.2016

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

echo apple1 | sed -e 's/\(a\)\(p*\)\(le\)1/\1\2\32/g'

Мы использовали три захвата:

  1. Первый, хранящийся в \1, содержит "a"
  2. Второй, хранящийся в \2, содержит последовательность "p" (в примере она содержит "pp").
  3. Третий, хранящийся в \3, содержит последовательность "le"

Теперь мы можем напечатать замену, используя захваченные совпадения: \1\2\32. Обратите внимание, что мы используем 3 значения захвата для создания «яблока», а затем добавляем 2. Это не будет интерпретироваться как переменная \32, потому что всего у нас может быть только 9 захватов.

Надеюсь, это поможет =)

person Janito Vaqueiro Ferreira Filho    schedule 02.10.2012
comment
да, но это не обрабатывает несколько совпадений в одной строке. - person jaf0; 19.06.2014
comment
Обратные ссылки предназначены для ссылки на сохраненные совпадения (как сформулировано в OP); и вопрос о замене строки В тех, а не в тех. - person 7heo.tk; 30.04.2015
comment
Добавление примера в комментарий 7heo.tk. Вы можете использовать обратные ссылки следующим образом: sed -e 's/\(a\)\(p*\)\(le\)1 \1\2\32/\1\2\33 \1\2\34/' заменит apple1 apple2 на apple3 apple4, и это также будет работать (если вы хотите) с appple1 appple2, в результате чего получится appple3 appple4. Однако это не заменит ни apple1 aple2, ни appple1 apple2, ни apple1 appple2, потому что они не имеют одной и той же строки, хранящейся в захваченных файлах (т. е. при сравнении слов они не совпадают). - person Janito Vaqueiro Ferreira Filho; 30.04.2015
comment
@JanitoVaqueiroFerreiraFilho Я не знал, что вы можете использовать обратные ссылки в части совпадения регулярного выражения. Вы знаете, если это POSIX? - person 7heo.tk; 30.04.2015
comment
@7heo.tk Да, AFAICT, это часть BRE (базовые регулярные выражения), которую должен реализовать каждый sed с поддержкой POSIX (pubs.opengroup.org/onlinepubs/007904975/basedefs/). - person Janito Vaqueiro Ferreira Filho; 30.04.2015
comment
@JanitoVaqueiroFerreiraFilho Я проверил это на реализациях GNU и BSD и обнаружил, что в обоих случаях sed 's/\(["'"'"']\)\(.*\)\1/\2/g' фактически дает строку между кавычками, будь то одинарные или двойные кавычки. Очень полезно, обязательно запомню, спасибо. - person 7heo.tk; 30.04.2015
comment
Без проблем. Мне нравится, что вы там сделали, чтобы сопоставить строки в кавычках. Я тоже запомню этот трюк :-) - person Janito Vaqueiro Ferreira Filho; 30.04.2015

вы можете сначала сопоставить шаблон, а затем изменить текст, если он соответствует:

echo "apple1" | sed '/apple/s/1/2/'    # gives you "apple2"

этот код изменяет 1 на 2 во всех строках, содержащих apple

person none    schedule 02.10.2012
comment
Спасибо! Я чувствую, что понимаю sed лучше после прочтения этого ответа. - person mwfearnley; 30.09.2018

Это может сработать для вас (GNU sed и Bash):

sed 's/apple1/sed "s|1|2|" <<<"&"/e' file
person potong    schedule 02.10.2012
comment
Хорошо, сработало... Обычно строка замены вставляется, но GNU sed использует флаг e для ее выполнения и вместо этого вставляет ее вывод. Выполняемая команда передает & (сопоставленный шаблон) в виде строки здесь в sed "s|1|2", где | заменяет более привычное /. - person mwfearnley; 30.09.2018