Найти и заменить в файле и перезаписать файл не работает, он очищает файл
Я хотел бы запустить поиск и заменить файл 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
- это содержимое файла, и поиск и замена выполнены.
Почему это происходит?
Ответы
Ответ 1
Когда shell видит > index.html
в командной строке, он открывает файл index.html
для записи, удаляя все предыдущее содержимое.
Чтобы исправить это, вам нужно передать опцию -i
на sed
, чтобы внести изменения в строку и создать резервную копию исходного файла, прежде чем он внесет изменения:
sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
Без .bak команда выйдет из строя на некоторых платформах, таких как Mac OSX.
Ответ 2
Альтернативный, полезный шаблон:
sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
Это имеет такой же эффект, не используя параметр -i
, и дополнительно означает, что если sed script не работает по какой-либо причине, входной файл не сбивается. Кроме того, если редактирование выполнено успешно, файл резервной копии не остается. Этот тип идиомы может быть полезен в Makefile.
Довольно много seds имеют параметр -i
, но не все из них; posix sed - это тот, который этого не делает. Поэтому, если вы нацелены на переносимость, лучше избегать.
Ответ 3
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html
Это делает глобальную замену на месте в файле index.html. Цитирование строки предотвращает проблемы с пробелом в запросе и замене.
Ответ 4
используйте параметр sed -i, например.
sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
Ответ 5
Чтобы изменить несколько файлов (и сохранить резервную копию каждого из них как .bak):
perl -p -i -e "s/\|/x/g" *
возьмет все файлы в каталоге и заменит |
на x
это называется "Perl pie" (легко, как пирог)
Ответ 6
Вам следует попробовать использовать опцию -i
для редактирования на месте.
Ответ 7
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html
Если у вас есть ссылка для добавления, попробуйте это. Найдите URL-адрес, указанный выше (начиная с https и заканчивая with.com здесь) и замените его на строку URL. Здесь я использовал переменную $pub_url
. s
здесь означает поиск, а g
означает глобальную замену.
Это работает!
Ответ 8
Предупреждение: это опасный метод! Он использует буферы ввода/вывода в linux и с определенными параметрами буферизации ему удается работать с небольшими файлами. Это интересное любопытство. Но не используйте это для реальной ситуации!
Помимо опции -i
sed
вы можете использовать утилиту 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
откроет файл для записи, и он будет очищен. Однако, если вы включите буферизацию всегда, вторая версия тоже будет работать.
Ответ 9
Проблема с командой
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
Ответ 10
И ответ ed
:
printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html
Чтобы повторить, что ответ codaddict ответил, оболочка обрабатывает перенаправление сначала, вытирая файл "input.html", а затем shell вызывает команду sed, передающую ее пустой файл.
Ответ 11
Вы можете использовать Vim в режиме Ex:
ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
-
%
выберите все строки
-
x
сохранить и закрыть
Ответ 12
Я искал вариант, где я могу определить диапазон строк и найти ответ. Например, я хочу изменить 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
Ответ 13
При всем должном уважении к приведенным выше правильным ответам всегда рекомендуется использовать сценарии "сухого запуска", так что вы не повредите свой файл и не должны начинать с нуля.
Просто попробуйте 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
Таким образом вы можете видеть и проверять вывод команды без усечения вашего файла.