Как можно продублировать строку, а затем выполнить поиск и замену в дубликате с помощью sed?

Как можно продублировать строку, а затем выполнить поиск и замену в дубликате с помощью sed?

Я пытаюсь дублировать строки в текстовом файле, которые содержат определенные специальные символы, но в дубликате заменить специальный символ на "обычные" символы ASCII. Конкретный вариант использования - символы с ударением.

Вход:

éva
test
frédéric

Желаемый результат:

éva
eva
test
frédéric
frederic

На данный момент я могу продублировать строки, содержащие éсимвол, но я не уверен, как искать и заменять в группе захвата.

Вот что у меня получилось на данный момент:

echo 'éva\ntest\nfrédéric' | sed 's/\(.*é.*\)/&\n\1/'

Могу ли я сделать это с sed? Если нет, я буду рад поработать с awk...

решение1

Вы можете сопоставить éи затем применить несколько команд:

sed '/é/{p;s/é/e/g;}'

Для любой строки é, содержащей , выводится текущее пространство шаблонов, затем все és заменяются на e(и снова выводится пространство шаблонов).

Эквивалент AWK:

awk '/é/{print; gsub(/é/, "e")}1'

sedКоманда sможет повторно использовать шаблон адреса:

sed '/é/{p;s//e/g;}'

а если все ваши замены состоят из одного символа, то yкоманда будет более эффективной:

sed '/é/{p;y/é/e/;}'

решение2

$ awk '1; gsub(/é/,"e")' file
éva
eva
test
frédéric
frederic

Вышеуказанные применения:

  1. Идиоматическое истинное условие, 1заставляющее awk выполнить действие по умолчанию — вывести текущую строку, затем:
  2. gsub()для замены любого és на es, и если это нашло/заменило любой és, то его положительный возврат, используемый в контексте условия, снова заставляет awk выполнить действие по умолчанию — вывести текущую (теперь измененную) строку.

Обратите внимание, что использование кода возврата для gsub()сообщения о том, éбыли ли найдены какие-либо символы s, избавляет нас от необходимости дважды указывать одно и то же регулярное выражение /é/в команде.

решение3

Еще один sedвариант - вдохновленный@EdMorton's awkответ

sed -n 'p;s/é/e/gp' file

решение4

Другой вариант,похоже на @Stephen Kitt's:

$ sed '/é/p;s/é/e/g'
éva
eva
test
frédéric
frederic

  • /é/pвыберите строки, содержащие éсимвол, и распечатайте.
  • s/é/e/gвывести предыдущие строки с заменой.

Связанный контент