sed редактировать файл на месте
Я пытаюсь выяснить, можно ли редактировать файл в одной команде sed без вручную потоковая передача отредактированного содержимого в новый файл, а затем переименование нового файла в исходное имя файла. Я попробовал -i вариант, но моя система Solaris сказала, что -i является незаконным вариантом. Есть ли другой способ?
13 ответов:
The
-iопции потоки отредактированного контента в новый файл, а затем переименовывает его за кулисами, в любом случае.пример:
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filenameи
sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filenameon macOS.
в системе, где
sedне имеет возможности редактировать файлы на месте, я думаю, что лучшим решением будет использоватьperl:perl -pi -e 's/foo/bar/g' file.txtхотя это создает временный файл, он заменяет оригинал, потому что пустой на месте суффикс/расширение было предоставлено.
обратите внимание, что в OS X вы можете получить странные ошибки, такие как "недопустимый код команды" или другие странные ошибки при выполнении этой команды. Чтобы исправить эту проблему попробуйте
sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>Это потому, что на OSX версии
sedна ждетextensionаргумент, поэтому ваша команда фактически анализируется какextensionаргумент и путь к файлу интерпретируются как код команды. Источник: https://stackoverflow.com/a/19457213
следующее прекрасно работает на моем mac
sed -i.bak 's/foo/bar/g' sampleмы заменяем foo с баром в файле образца. Резервная копия исходного файла будет сохранена в образце.бак
для редактирования inline без резервного копирования используйте следующую команду
sed -i'' 's/foo/bar/g' sample
одна вещь, чтобы отметить,
sedне может писать файлы самостоятельно, так как единственная цель sed-выступать в качестве редактора в "потоке" (т. е. конвейеры stdin, stdout, stderr и другие>&nбуферы, сокеты и тому подобное). Имея это в виду, вы можете использовать другую командуteeдля записи результатов в файл. Другой вариант-создать патч из конвейера содержимого вdiff.метод тройник
sed '/regex/' <file> | tee <file>патч метод
sed '/regex/' <file> | diff -p <file> /dev/stdin | patchобновление:
кроме того, обратите внимание, что патч получит файл для изменения из строки 1 вывода diff:
патчу не нужно знать, к какому файлу обращаться, так как он находится в первой строке вывода из diff:
$ echo foobar | tee fubar $ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin *** fubar 2014-03-15 18:06:09.000000000 -0500 --- /dev/stdin 2014-03-15 18:06:41.000000000 -0500 *************** *** 1 **** ! foobar --- 1 ---- ! fubar $ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch patching file fubar
невозможно сделать то, что вы хотите с
sed. Даже версииsedв поддержку-iопция для редактирования файла на месте сделать именно то, что вы явно заявили, что вы не хотите: они пишут во временный файл, а затем переименовать файл. Но, возможно, вы можете просто использоватьed. Например, чтобы изменить все вхожденияfooдоbarв файлеfile.txt, вы можете сделать:echo ',s/foo/bar/g; w' | tr \; '2' | ed -s file.txtсинтаксис похож на
sed, но конечно не точно тот же.но, возможно, вы должны рассмотреть, почему вы не хотите использовать переименованный временный файл. Даже если у вас нет
-iподдержкаsed, вы можете легко написать сценарий, чтобы сделать работу за вас. Вместоsed -i 's/foo/bar/g' file, вы могли бы сделатьinline file sed 's/foo/bar/g'. Такой сценарий-это тривиально, чтобы написать. Например:#!/bin/sh -e IN= shift trap 'rm -f $tmp' 0 tmp=$( mktemp ) <$IN "$@" >$tmp && cat $tmp > $IN # preserve hard linksдолжно быть достаточно для большинства применений.
sed поддерживает редактирование на месте. От
man sed:-i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied)пример:
Допустим у вас есть файлhello.txtС текстом:hello world!если вы хотите сохранить резервную копию старого файла, использовать:
sed -i.bak 's/hello/bonjour' hello.txtвы получите два файла:
hello.txtсодержание:bonjour world!и
hello.txt.bakсо старым содержимым.если вы не хотите хранить копию, просто не передавайте параметр расширения.
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txtследует сохранить все жесткие ссылки, так как вывод направляется обратно, чтобы перезаписать содержимое исходного файла и избежать необходимости в специальной версии sed.
если вы заменяете такое же количество символов и после тщательного чтения редактирование файлов"на месте"...
вы также можете использовать оператор перенаправления
<>открыть файл для чтения и записи:sed 's/foo/bar/g' file 1<> fileпосмотреть это видео:
$ cat file hello i am here # see "here" $ sed 's/here/away/' file 1<> file # Run the `sed` command $ cat file hello i am away # this line is changed nowС справочное руководство Bash → 3.6.10 Открытие дескрипторов файлов для чтения и записи:
оператор перенаправления
[n]<>wordвызывает файл, имя которого является расширением word, который будет открыт для как чтение, так и запись на файловый дескриптор n или на файловый дескриптор 0 если N не указано. Если файл не существует, он создается.
вы не указали, какую оболочку вы используете, но с zsh вы можете использовать
=( )построить для достижения этой цели. Что-то вроде:cp =(sed ... file; sync) file
=( )похож на>( )но создает временный файл, который автоматически удаляется приcpзавершается.
Как сказал Манипенни в Skyfall: "иногда старые способы лучше." Кинкейд сказал что-то подобное позже.
$ printf', s / false / true/g\nw\n ' / ed {YourFileHere}
счастливое редактирование на месте. Добавлена '\nw\n ' для записи файла. Приносим извинения за задержку ответа на запрос.
очень хорошие примеры. У меня была проблема с редактированием на месте многих файлов, и опция-i кажется единственным разумным решением, использующим ее в команде find. Вот скрипт для добавления "version:" перед первой строкой каждого файла:
find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
Comments