Я пытаюсь выяснить, возможно ли отредактировать файл в одной команде sed без потоковой передачи отредактированного содержимого вручную в новый файл, а затем переименовать новый файл в исходное имя файла. Я попробовал -i
вариант, но моя система Solaris сказала, что -i
это незаконный вариант. Есть ли другой способ?
300
-i
это опция в GNU SED, но не в стандартном SED. Тем не менее, он передает содержимое в новый файл, а затем переименовывает файл, так что это не то, что вы хотите.Ответы:
-i
Вариант потоки отредактированного содержимого в новый файл , а затем переименовывает его за кулисами, во всяком случае.Пример:
и
на macOS .
источник
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
В системе, где
sed
нет возможности редактировать файлы, я думаю, что лучшим решением было бы использоватьperl
:Несмотря на то, что это создает временный файл, он заменяет оригинальный, потому что был предоставлен пустой суффикс / расширение на месте.
источник
sudo
. На мой взгляд, вопрос заключается в том, как избежать создания и переименования временного файла вручную без необходимости устанавливать последнюю версию GNU или BSDsed
. Просто используйте Perl.sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
. То, что редактирование на месте выполняет переименование с использованием временного файла, не означает, что он / она должен выполнить переименование вручную, когда опция недоступна. Существуют и другие инструменты, которые могут делать то, что он / она хочет, и Perl - очевидный выбор. Как это не ответ на оригинальный вопрос?sed
. Вопрос был на самом деле очень хорошим, но его ценность уменьшилась людьми, которые либо не умеют читать справочные страницы, либо не могут быть обеспокоены фактическим чтением вопросов здесь, на SO.Обратите внимание, что в OS X вы можете получить странные ошибки, такие как «неверный код команды» или другие странные ошибки при выполнении этой команды. Чтобы решить эту проблему, попробуйте
Это происходит потому , что на версию OSX из
sed
, то-i
вариант ожидаетextension
аргумент , так ваша команда на самом деле разобрана в качествеextension
аргумента , и путь к файлу интерпретируются как код команды. Источник: https://stackoverflow.com/a/19457213источник
brew install gnu-sed
вместе с aPATH
позволит вам использовать GNU-версию sed. Спасибо за упоминание; определенный скребок головы.Следующее отлично работает на моем Mac
Мы заменяем foo на bar в файле примера. Резервная копия исходного файла будет сохранена в sample.bak
Для редактирования inline без резервного копирования, используйте следующую команду
источник
Стоит отметить, что
sed
нельзя создавать файлы самостоятельно, поскольку единственная цель sed - выступать в качестве редактора «потока» (т. Е. Конвейеров stdin, stdout, stderr и других>&n
буферов, сокетов и т. П.). Имея это в виду, вы можете использовать другую команду,tee
чтобы записать вывод обратно в файл. Другим вариантом является создание патча из конвейера контентаdiff
.Тройник метод
Патч метод
ОБНОВИТЬ:
Также обратите внимание, что patch исправит файл из строки 1 вывода diff:
Патчу не нужно знать, к какому файлу обращаться, так как он находится в первой строке вывода diff:
источник
/dev/stdin 2014-03-15
, ответил 7 января - ты путешественник во времени?/dev/stdin
не существует, поэтому вы должны заменить/dev/stdin
на '-', один дефис без кавычек, поэтому должны работать следующие команды:$ sed 's/oo/u/' fubar | diff -p fubar -
и$ sed 's/oo/u/' fubar | diff -p fubar - | patch
patch
не будет усекать также. Я думаю, что сохранение вывода в другой файл и затемcat
-ing в оригинал будет безопаснее.Невозможно делать то, что вы хотите с
sed
. Даже версии,sed
которые поддерживают-i
возможность редактирования файла на месте, делают именно то, что вы явно заявили, что вы не хотите: они записывают во временный файл, а затем переименовывают файл. Но, возможно, вы можете просто использоватьed
. Например, чтобы изменить все вхожденияfoo
вbar
в файлеfile.txt
, вы можете сделать:Синтаксис похож на
sed
, но, конечно, не совсем то же самое.Но, возможно, вам следует подумать, почему вы не хотите использовать переименованный временный файл. Даже если у вас нет
-i
поддержкиsed
, вы можете легко написать сценарий, который сделает всю работу за вас. Вместо этогоsed -i 's/foo/bar/g' file
вы могли бы сделатьinline file sed 's/foo/bar/g'
. Такой сценарий тривиально написать. Например:должно быть достаточно для большинства применений.
источник
inline
и вызвал это, как описано выше:inline inputfile sed 's/foo/bar/g'
ed
только ответ, который действительно на месте. Первый раз, когда мне нужноed
. Спасибо. Небольшая оптимизация заключается в использованииecho -e ",s/foo/bar/g\012 w"
илиecho $',s/foo/bar/g\012 w'
там, где shell позволяет избежать лишнихtr
вызовов.ed
на самом деле не делает модификации на месте. Исходя изstrace
вывода, GNUed
создает временный файл, записывает изменения во временный файл, а затем перезаписывает весь исходный файл, сохраняя жесткие ссылки. Исходя изtruss
вывода, Solaris 11ed
также использует временный файл, но после сохранения с помощьюw
команды переименовывает временный файл в исходное имя файла , уничтожая любые жесткие ссылки.ed
что поставляется с текущими макосами (Mojave, что бы ни значил этот маркетинговый жаргон), все еще сохраняет жесткие ссылки. YMMVВы могли бы использовать vi
источник
sed поддерживает редактирование на месте. От
man sed
:Пример :
Допустим, у вас есть файл
hello.txt
с текстом:Если вы хотите сохранить резервную копию старого файла, используйте:
В итоге вы получите два файла:
hello.txt
с содержимым:и
hello.txt.bak
со старым содержанием.Если вы не хотите сохранять копию, просто не передавайте параметр extension.
источник
Вы не указали, какую оболочку вы используете, но с помощью zsh вы можете использовать
=( )
конструкцию для достижения этой цели. Что-то вроде:=( )
аналогично,>( )
но создает временный файл, который автоматически удаляется приcp
завершении.источник
Следует сохранить все жесткие ссылки, поскольку выходные данные направляются обратно, чтобы перезаписать содержимое исходного файла, и избегают необходимости в специальной версии sed.
источник
Если вы заменяете одинаковое количество символов и после внимательного прочтения редактирования файлов на месте ...
Вы также можете использовать оператор перенаправления,
<>
чтобы открыть файл для чтения и записи:Смотрите это в прямом эфире:
Из Справочного руководства Bash → 3.6.10 Открытие файловых дескрипторов для чтения и записи :
источник
Как Moneypenny сказал в Skyfall: «Иногда старые способы лучше». Кинкейд сказал нечто подобное позже.
Приятного редактирования на месте. Добавлен \ nw \ n для записи файла. Извиняюсь за задержку ответа на запрос.
источник
|
. @MattMontag\n
. [range] s / <old> / <new> / <flag> - это форма команды замены - парадигма, все еще встречающаяся во многих других текстовых редакторах (хорошо, vim, прямой потомок ed). В любом случае,g
флаг обозначает «глобальный» и означает «каждый экземпляр в каждой строке, на которую вы смотрите». Диапазон3,5
смотрит на линии 3-5.,5
смотрит на StartOfFile-5,3,
смотрит на строки 3-EndOfFile и,
смотрит на StartOfFile-EndOfFile. Глобальная команда подстановки в каждой строке, которая заменяет «false» на «true». Затемw
вводится команда записи .Очень хорошие примеры. У меня была проблема с редактированием множества файлов, и опция -i, кажется, единственное разумное решение, использующее его в команде find. Вот скрипт для добавления «version:» перед первой строкой каждого файла:
источник