Как найти и заменить несколько игл одним словом через одно выражение?

8

Предположим, у вас есть текстовый файл:

foo fnord bar
bizz foo poit

И теперь я хотел бы заменить оба слова "foo" и "bar" на "narf".

Я знаю, что мог бы использовать:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

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

Попадая в некоторые руководства, я думаю, что труба должна соответствовать моим потребностям, но я пытался

sed -e 's/foo|bar/narf/g' -i fileName

и это не сработало, и даже не выдает ошибку.

Что я здесь не так делаю?

k0pernikus
источник

Ответы:

10

Используйте -rопцию для расширенного синтаксиса регулярных выражений:

sed -r -e 's/foo|bar/narf/g'

В противном случае избежать дизъюнкции как \|:

sed -e 's/foo\|bar/narf/g'
Стефан Хименес
источник
6

Существует много вариантов синтаксиса регулярных выражений . Самые первые инструменты в мире Unix, которые имели регулярные выражения, не имели полных возможностей регулярных выражений, только наборы символов ( […]и .), repetition ( *) и якоря строк ( ^и $). Базовые регулярные выражения имеют только эти операторы. Sed является инструментом старой школы и использует базовые регулярные выражения.

Многие реализации sed имеют расширения для полного соответствия регулярному выражению. Поскольку персонаж |выступает за себя, его нужно использовать \|для чередования, а так же \(и \)для группировки. Обратите внимание, что стандарт POSIX не \|требует поддержки в основных регулярных выражениях , а в некоторых системах (например, OpenBSD ) его нет.

В некоторых версиях sed есть возможность переключаться на расширенные регулярные выражения , где (…)используется для группировки и |чередования. С GNU sed (т.е. под Linux или Cygwin) или Busybox , передайте -rопцию. На FreeBSD или OSX передайте -Eопцию.

Если у вашего sed нет чередования, вы можете awkвместо этого позвонить . Это предписано POSIX , но немного многословно для этой задачи, и оно не поддерживает обратные ссылки.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

Кстати, только GNU и Busybox sed поддерживают замену файлов на месте. Awk и другие версии sed этого не делают. См. Можно ли сделать `cut` для изменения файла на месте?

Если у вас есть Perl, он часто удобен для обработки текста одним способом. Большая часть того, что легко в sed, awk и остальном, не намного сложнее в Perl, и вы можете получить удовольствие от изучения одного (если сложного) инструмента.

perl -i -pe 's/foo|bar/narf/g' fileName
Жиль "ТАК - перестань быть злым"
источник
0

Вы можете использовать Vim в режиме Ex:

ex -sc '%s/\vPA|QU/RO/g|x' file
  1. % выбрать все строки

  2. s замена

  3. \v включить магию

  4. g глобальная замена

  5. x сохранить и закрыть

Стивен Пенни
источник