it-swarm.com.ru

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

Я хотел бы запустить поиск и замену файла 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 - это содержимое файла, и поиск и замена были выполнены.

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

571
BBales

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

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

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

Без .bak команда не будет работать на некоторых платформах, таких как Mac OSX.

880
codaddict

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

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

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

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

201
Norman Gray
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

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

86
Rich Apodaca

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

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
56
Kevin

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

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

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

18
Stenemo

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

14
uloBasEI
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

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

Оно работает !

6
Kaey

Предупреждение: это опасный метод! Он использует буферы ввода/вывода в linux и с определенными параметрами буферизации ему удается работать с небольшими файлами. Это интересное любопытство. Но не используйте это для реальной ситуации!

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

От man:

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

Итак, решение будет таким:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

- здесь tee повторяется, чтобы убедиться, что конвейер буферизован. Затем все команды в конвейере блокируются, пока они не получат некоторый ввод для работы. Каждая команда в конвейере начинается, когда вышестоящие команды записывают 1 буфер байтов (размер определен где-то ) на вход команды. Таким образом, последняя команда tee index.html, которая открывает файл для записи и, следовательно, очищает его, выполняется после завершения восходящего конвейера и вывода в буфер в конвейере.

Скорее всего, следующее не будет работать:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

- он будет запускать обе команды конвейера одновременно без какой-либо блокировки. (Без блокировки конвейер должен передавать байты построчно, а не буфер за буфером. То же, что и при запуске cat | sed s/bar/GGG/. Без блокировки он более интерактивен и обычно конвейеры из всего 2 команд выполняются без буферизации и блокировки. Более длинные конвейеры буферизуются.) tee index.html откроет файл для записи и будет очищен. Однако, если вы включите буферизацию всегда, вторая версия тоже будет работать.

4
xealits

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

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
4
Andrzej Pronobis

И ответ ed:

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

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

3
glenn jackman

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

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

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

2
Steven Penny

Я искал вариант, где я могу определить диапазон строк и нашел ответ. Например, я хочу изменить 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
0
user8117884

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

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

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

OR

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

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

0
Nestor Milyaev