Я пытаюсь выяснить, возможно ли отредактировать файл в одной команде sed без  вручную потокового редактирования отредактированного содержимого в новый файл, а затем переименовать новый файл в исходное имя файла, Я попробовал параметр -i, но моя система Solaris сообщила, что -i является незаконным вариантом. Есть ли другой способ?
Sed редактировать файл на месте
Ответ 1
 Опция  -i передает измененный контент в новый файл, а затем переименовывает его за кулисами.
Пример:
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
а также
sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
на macOS.
Ответ 2
В системе, где sed не имеет возможности редактировать файлы на месте, я думаю, что лучшим решением было бы использовать perl:
perl -pi -e 's/foo/bar/g' file.txt
Хотя это и создает временный файл, он заменяет оригинал, потому что был добавлен суффикс/расширение пустого места.
Ответ 3
Обратите внимание, что на OS X вы можете получить странные ошибки, такие как "недопустимый код команды" или другие странные ошибки при выполнении этой команды. Чтобы исправить эту проблему, попробуйте
sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
Это связано с тем, что в версии OSX sed параметр -i ожидает аргумент extension, поэтому ваша команда фактически анализируется как аргумент extension, а путь к файлу интерпретируется как код команды. Источник: fooobar.com/questions/33995/...
Ответ 4
Следующее работает отлично на моем mac
sed -i.bak 's/foo/bar/g' sample
Мы заменяем foo на bar в файле образца. Резервное копирование исходного файла будет сохранено в sample.bak
Для редактирования встроенного без резервного копирования используйте следующую команду
sed -i'' 's/foo/bar/g' sample
Ответ 5
Одно замечание: sed не может самостоятельно записывать файлы, поскольку единственная цель sed - действовать как редактор в потоке (например, конвейеры stdin, stdout, stderr и других >&n буферов, розетки и т.п.). Имея это в виду, вы можете использовать другую команду tee для записи вывода обратно в файл. Другой вариант - создать патч из конвейера содержимого в diff.
Метод тройника
 
sed '/regex/' <file> | tee <file>
Метод исправления
 
sed '/regex/' <file> | diff -p <file> /dev/stdin | patch
UPDATE:
Также обратите внимание, что патч получит файл для изменения из строки 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
Ответ 6
Невозможно выполнить то, что вы хотите, с помощью sed. Даже версии sed, которые поддерживают параметр -i для редактирования файла на месте, делают именно то, что вы явно заявили, что не хотите: они записывают во временный файл и затем переименовывают файл. Но, возможно, вы можете просто использовать ed. Например, чтобы изменить все вхождения от foo до bar в файле file.txt, вы можете сделать:
echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt
Синтаксис похож на sed, но, конечно, не совсем то же самое.
Но, возможно, вам стоит подумать, почему вы не хотите использовать переименованный временный файл. Даже если у вас нет поддержки -i sed, вы можете легко написать script, чтобы выполнить эту работу для вас. Вместо sed -i 's/foo/bar/g' file вы можете сделать inline file sed 's/foo/bar/g'. Такой script тривиально писать. Например:
#!/bin/sh -e
IN=$1
shift
trap 'rm -f $tmp' 0
tmp=$( mktemp )
<$IN "[email protected]" >$tmp && cat $tmp > $IN  # preserve hard links
должен быть достаточным для большинства целей.
Ответ 7
 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 со старым контентом.
Если вы не хотите сохранять копию, просто не передавайте параметр расширения.
Ответ 8
Вы можете использовать vi
vi -c '%s/foo/bar/g' my.txt -c 'wq'
Ответ 9
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt
Сохранять все жесткие ссылки, так как вывод перенаправляется на перезапись содержимого исходного файла и позволяет избежать необходимости в специальной версии sed.
Ответ 10
Если вы заменяете одинаковое количество символов и после тщательного чтения "На месте" редактирование файлов...
Вы также можете использовать оператор перенаправления <>, чтобы открыть файл для чтения и записи:
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вызывает файл, имя которого является расширением слова, которое нужно открыть для как чтение, так и запись в дескрипторе файла n или в дескрипторе файла 0 если n не указано. Если файл не существует, он создается.
Ответ 11
Вы не указали, какую оболочку используете, но с zsh вы можете использовать конструкцию =( ) для достижения этой цели. Что-то вроде:
cp =(sed ... file; sync) file
 =( ) похож на >( ), но создает временный файл, который автоматически удаляется при завершении cp.
Ответ 12
Как Moneypenny сказал в Skyfall: "Иногда старые способы лучше". Кинкейд сказал нечто подобное позже.
$ printf ',s/false/true/g\nw\n' | ed {YourFileHere}
Приятного редактирования на месте. Добавлен \nw\n для записи файла. Извиняюсь за задержку ответа на запрос.
Ответ 13
Очень хорошие примеры. У меня была проблема редактирования на месте многих файлов, и опция -i, по-видимому, является единственным разумным решением, использующим его в команде find. Здесь script добавить "версию:" перед первой строкой каждого файла:
find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
