Команда sed найти и заменить в файле и перезаписать файл не работает, он очищает файл

459

Я хотел бы запустить поиск и заменить файл HTML через командную строку.

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

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

Когда я запустил это и посмотрел на файл после этого, он пуст. Он удалил содержимое моего файла.

Когда я запустил это после восстановления файла снова:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdout - это содержимое файла, и поиск и замена выполнены.

Почему это происходит?

  • 12
    Альтернатива Perl: perl -pi -w -e 's/STRING_TO_REPLACE/REPLACE_WITH/g;' index.html
  • 0
    очень sed команда sed для поиска строки и замены всей строки: stackoverflow.com/questions/11245144/…
Теги:
sed

13 ответов

673
Лучший ответ

Когда shell видит > index.html в командной строке, он открывает файл index.html для записи, удаляя все предыдущее содержимое.

Чтобы исправить это, вам нужно передать опцию -i на sed, чтобы внести изменения в строку и создать резервную копию исходного файла, прежде чем он внесет изменения:

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

Без .bak команда выйдет из строя на некоторых платформах, таких как Mac OSX.

  • 20
    Говоря truncates the file а не opens the file вероятно, делает его более понятным.
  • 12
    По крайней мере, на моем Mac первое предложение не работает ... если вы выполняете замену файла на месте, вы должны указать расширение. Вы можете, по крайней мере, передать расширение нулевой длины: sed -i 's / STRING_TO_REPLACE / STRING_TO_REPLACE_IT / g index.html
Показать ещё 9 комментариев
171

Альтернативный, полезный шаблон:

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

Это имеет такой же эффект, не используя параметр -i, и дополнительно означает, что если sed script не работает по какой-либо причине, входной файл не сбивается. Кроме того, если редактирование выполнено успешно, файл резервной копии не остается. Этот тип идиомы может быть полезен в Makefile.

Довольно много seds имеют параметр -i, но не все из них; posix sed - это тот, который этого не делает. Поэтому, если вы нацелены на переносимость, лучше избегать.

  • 30
    +1 за рассмотрение переносимости
  • 8
    +1 за отсутствие резервной копии файла и не засорение входного файла, если редактирование не удалось. Работал на Mac без нареканий.
Показать ещё 7 комментариев
61
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

Это делает глобальную замену на месте в файле index.html. Цитирование строки предотвращает проблемы с пробелом в запросе и замене.

48

используйте параметр sed -i, например.

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
  • 4
    работает на меня Mac. Принятый ответ не
  • 0
    Что это значит? sed: -i не может быть использован с stdin
Показать ещё 3 комментария
16

Чтобы изменить несколько файлов (и сохранить резервную копию каждого из них как .bak):

perl -p -i -e "s/\|/x/g" *  

возьмет все файлы в каталоге и заменит | на x это называется "Perl pie" (легко, как пирог)

  • 1
    Приятно видеть кого-то, кто хочет взглянуть на постановку задачи, а не только на теги. OP не указывал в качестве требования sed а использовал его только в качестве уже опробованного инструмента.
12

Вам следует попробовать использовать опцию -i для редактирования на месте.

5

Помимо опции -i sed вы можете использовать утилиту tee.

От man:

tee - чтение со стандартного ввода и запись на стандартный вывод и файлы

Таким образом, решение будет:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html
  • 3
    Выходной файл tee также открывается немедленно, что приводит к пустому index.html для всей команды.
  • 3
    Это приведет к повреждению любого входного файла, который больше буфера конвейера (который обычно составляет 64 КБ) . (@sjngm: файл не усекается мгновенно, как с > , но точка зрения состоит в том, что это неработающее решение, которое может привести к потере данных).
4
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

Если у вас есть ссылка для добавления, попробуйте это. Найдите URL-адрес, указанный выше (начиная с https и заканчивая with.com здесь) и замените его на строку URL. Здесь я использовал переменную $pub_url. s здесь означает поиск, а g означает глобальную замену.

Это работает!

3

Проблема с командой

sed 'code' file > file

заключается в том, что file усекается оболочкой до того, как sed фактически получает ее. В результате вы получаете пустой файл.

Для этого нужно использовать -i для редактирования на месте, как и другие ответы. Однако это не всегда то, что вы хотите. -i создаст временный файл, который затем будет использоваться для замены исходного файла. Это проблематично, если исходный файл был ссылкой (ссылка будет заменена обычным файлом). Если вам нужно сохранить ссылки, вы можете использовать временную переменную для хранения вывода sed, прежде чем записывать его обратно в файл, например:

tmp=$(sed 'code' file); echo -n "$tmp" > file

Еще лучше использовать printf вместо echo, так как echo скорее всего обработает \\ как \ в некоторых оболочках (например, тире):

tmp=$(sed 'code' file); printf "%s" "$tmp" > file
  • 1
    +1 за сохранение ссылок. Он также работает с временным файлом: sed 'code' file > file.tmp; cat file.tmp > file; rm file.tmp
3

И ответ ed:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

Чтобы повторить, что ответ codaddict ответил, оболочка обрабатывает перенаправление сначала, вытирая файл "input.html", а затем shell вызывает команду sed, передающую ее пустой файл.

  • 2
    быстрый вопрос, почему люди продолжают давать « ed версию» ответов sed ? это работает быстрее?
  • 6
    Некоторые sed не используют -i для редактирования на месте. ed вездесущ и позволяет вам сохранить ваши изменения в исходном файле. Плюс всегда хорошо иметь много инструментов в своем наборе.
Показать ещё 1 комментарий
1

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

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  • % выберите все строки

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

0

При всем должном уважении к приведенным выше правильным ответам всегда рекомендуется использовать сценарии "сухого запуска", так что вы не повредите свой файл и не должны начинать с нуля.

Просто попробуйте script вывести вывод в командную строку вместо записи в файл, например:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

ИЛИ

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

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

0

Я искал вариант, где я могу определить диапазон строк и найти ответ. Например, я хочу изменить host1 на host2 из строки 36-57.

sed '36,57 s/host1/host2/g' myfile.txt > myfile1.txt

Вы можете использовать опцию gi, чтобы игнорировать случай символа.

sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt

Ещё вопросы

Сообщество Overcoder
Наверх
Меню