Проверьте рекурсивный поиск sed и замените его перед запуском

13

Есть ли способ запустить пробный рекурсивный поиск и заменить его sed, прежде чем запускать его? Я просто хочу распечатать результаты, прежде чем делать поиск и замену. Что-то вроде повторения результатов,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
user251482
источник
Сделайте копию данных, запустите команду, проверьте результат.
Кусалананда

Ответы:

10

Вы можете запустить sedбез -iи шаг за шагом с выходомless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Затем запустите sedс -i.bakдля создания резервных копий , которые вы можете Diff впоследствии

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Изменить: как предлагается в комментарии, используйте grep --null | xargs -0. Это приводит к тому, что имена файлов заканчиваются нулевым байтом, что делает его безопасным для имен файлов с необычными символами, такими как символ новой строки. Да, \nявляется допустимым символом в имени файла Unix. Единственными запрещенными символами являются слеш /и нулевой символ\0

grebneke
источник
Интересно, что я попытался найти значение -i, но оно не было указано в разделе man sed. Ваше решение сработало. Как, по вашему мнению, лучше всего перечислить строки, а не весь файл? Вместо того, чтобы тратить меньше grep term2, который работал, но я также получил некоторые странные символы.
user251482
@ user251482 - «Просто перечислите строки», как в «Просмотр различий между старым и новым файлом»?
Гребнеке
1
@StephaneChazelas Да, или даже лучше, grep -rl --nullпоскольку в OP не указана ОС, и это -Zозначает что-то другое в BSD / OSX (распаковка). --nullодинаково на GNU и BSD
grebneke
1
@grebneke. Хороший вопрос, но обратите внимание, что OP использует синтаксис GNU sed, поэтому мы можем предположить, что он не на BSD. Обратите внимание, что grepэто GNU grep для FreeBSD и NetBSD. На NetBSD -Zвсе еще означает --null(согласно странице руководства), но я согласен --null более переносим. Также обратите внимание, что ни --null, ни -Z не работают на OpenBSD
Стефан Шазелас
1
@grebneke, это sed -i '' -e s/.../в BSD sed(там нет опций)
Стефан Шазелас
5

Используйте sedс findвместоgrep

Прежде всего, я бы использовал, findа не grep, и это по трем причинам:

  1. findпозволяет более точный выбор файлов. Например, grep -r string *.txtвыдаст файлы только в текущем каталоге; не те в подкаталогах.
  2. findпоставляется с мощной -execопцией, которая устраняет необходимость всей --null … |xargs 0конструкции.
  3. В -readableи -writableварианты findпомешают тратить время на файлы , которые не могут быть доступны.

Тест захвата

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

$ find . -exec grep term1 {} \;

или более конкретно:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Прогон, репетиция

Теперь приступайте к sedпробному запуску. sedВариантом -nявляется синонимом --quietи pв самом конце sedвыражения напечатает текущее пространство картины.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

или более конкретно:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

выполнение

Если все выглядит нормально, выдает окончательную команду, заменив sedопцию -nна -iдля «на месте» и удаления pв конце.

$ find . -exec sed -i 's/term1/term2/g' {} \;

или более конкретно:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Больше findпримеров

Больше findпримеров можно найти здесь .

Серж Строобандт
источник