Редактирование на месте с помощью sed в OS X

Я хотел бы отредактировать файл с помощью sed в OS X. Я использую следующую команду:

sed 's/oldword/newword/' file.txt

Выход отправляется на терминал. file.txt не изменяется. Изменения сохраняются в file2.txt с помощью этой команды:

sed 's/oldword/newword/' file1.txt > file2.txt

Однако я не хочу другой файл. Я просто хочу отредактировать file1.txt. Как я могу это сделать?

Я пробовал флаг -i. Это приводит к следующей ошибке:

sed: 1: "file1.txt": invalid command code f

8 ответов

Решение

Вы можете правильно использовать флаг -i, предоставив ему суффикс для добавления в файл резервной копии. Расширяем ваш пример:

sed -i.bu 's/oldword/newword/' file1.txt

Вам дадут два файла: один с именем file1.txt, который содержит подстановку, а другой с именем file1.txt.bu, который имеет исходное содержимое.

Мягко опасный

Если вы хотите деструктивно перезаписать исходный файл, используйте что-то вроде:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

Из-за способа анализа строки между флагом параметра и его аргументом требуется пробел, поскольку аргумент имеет нулевую длину.

Помимо возможной поломки вашего оригинала, я не знаю никаких дальнейших опасностей обмана сэд таким образом. Следует отметить, однако, что если этот вызов sed является частью сценария, Unix Way™ (IMHO) будет использовать sed неразрушающе, проверьте, что он вышел чисто, и только затем удалите посторонний файл.

The -iфлаг, вероятно, не работает для вас, потому что вы следовали примеру GNU sed , в то время как macOS использует BSD sed , и у них немного другой синтаксис.

Все остальные ответы говорят вам, как исправить синтаксис для работы с BSD sed. Альтернативой является установка GNU sed на macOS с помощью:

      brew install gsed

а затем использовать его вместо sedверсия, поставляемая с macOS (обратите внимание на gпрефикс), например:

      gsed -i 's/oldword/newword/' file1.txt

Если вы хотите, чтобы команды GNU sed всегда были переносимы на вашу macOS, вы можете добавить каталог «gnubin» к своему пути, добавив что-то вроде этого в свой .bashrc/ .zshrcфайл (выполнить brew info gsedчтобы увидеть, что именно вам нужно сделать):

      export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

и с этого момента GNU sed становится вашим sed по умолчанию, и вы можете просто запустить:

      sed -i 's/oldword/newword/' file1.txt

У меня похожая проблема с MacOS

sed -i '' 's/oldword/newword/' file1.txt

не работает, но

sed -i"any_symbol" 's/oldword/newword/' file1.txt

работает хорошо.

sed -i -- "s/https/http/g" file.txt

Ты можешь использовать -i'' (--in-place) за sed как уже предлагалось. Смотрите: -i аргумент на месте, однако обратите внимание, что -i опция нестандартных расширений FreeBSD и может быть недоступна в других операционных системах. во-вторых sed является редактором S Tream ED, а не редактором файлов.


Альтернативный способ - использовать встроенную замену в режиме Vim Ex, например:

$ ex +%s/foo/bar/g -scwq file.txt

и для нескольких файлов:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Для рекурсивного редактирования всех файлов вы можете использовать **/*.* если оболочка поддерживает это (включить shopt -s globstar ).


Другой способ заключается в использовании gawk и его новое расширение "на месте", такое как:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

Это создает файлы резервных копий. Например sed -i -e 's/hello/hello world/' testfile для меня создает файл резервной копии, testfile-e, в том же каталоге.

Ты можешь использовать,

sed -i -e 's ///'

Например, sed -i -e 's/Hello/Bye/' file.txt

это работает безупречно в Mac

Если вам нужно заменить более одного слова:

      sed -i '' -e 's/_tools/tools/' -e 's/_static/static/' test.txt
Другие вопросы по тегам