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

155

Я хочу отредактировать файл с помощью 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
Воскресенье понедельник
источник
3
Какую именно команду вы используете, когда пробуете -iфлаг?
eldarerathis

Ответы:

298

Вы можете -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 таким образом. Однако следует отметить, что, если этот вызов sedявляется частью сценария, The Unix Way ™ (IMHO) должен использовать sedнеразрушающий контроль, проверить, что он завершился правильно, и только затем удалить посторонний файл.

строгать
источник
Вы правы, я пропустил расширение после флага -i. -i''Опасно ли это по какой-либо причине, кроме потенциально испорченного исходного файла (и отсутствия резервной копии)?
Воскресенье, понедельник,
Согласно sedстранице руководства, если у вас закончится дисковое пространство на устройстве, вы можете повредить файл на полпути и получить плохой результат. Если вы работаете с локальным контролем sed -i ""версий без резервных копий, все должно быть в порядке большую часть времени (или непосредственно git init && git add -A . && git commit -m 'backup'перед запуском sed в -iрежиме).
cfeduke
2
Я нашел умеренно опасный бит особенно полезным. +1
Андре
5
BSD sed требует, чтобы после флага -i не было пробела. Итак, -i''действительно, но -i ''это не так.
Тодд А. Джейкобс
3
Ах! BSD sed игнорирует символ '\ n' и вместо этого печатает 'n'! Я просто собираюсь заменить BSD sed на GNU sed на моем Mac!
nterry
22

У меня аналогичная проблема с MacOS

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

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

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

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

ksnt
источник
Сейчас все наоборот. sed -i '' <file>работает, но sed -i'' <file>больше не работает
Зохайб Аманзай
7
sed -i -- "s/https/http/g" file.txt
взволнованный
источник
Когда я пробую это на Mac, я получаю сообщение об ошибке «sed: -i не может использоваться с stdin».
Кристофер Брэдшоу,
4

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


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

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

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

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

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


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

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
Kenorb
источник
4

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

JustADude
источник
То же самое и с Mac OS Catalina. Передача -i и -e по отдельности (НЕ -ie вместе!) Создает файл резервной копии с добавленным -e.
Дэниел Кеснер,
1

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

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

Пример:

sed -i -e 's/Hello/Bye/' file.txt

Это работает безупречно на Mac .

Винсент Лал
источник
2
Это создает для меня файл резервной копии в Mac OS Catalina с добавленным '-e'.
Дэниел Кеснер,
1
Это неправильно для macOS. Пожалуйста, взгляните на страницу "man sed" там. -iтребуется аргумент для macOS. Поскольку вы не указываете один, он использует -e, в результате чего получается второй файл с -eдобавленным. -eне существует в macOS, это так -E. Итак, правильная команда для macOSsed -i '' -E 's/Hello/Bye/' file.txt
Марк Дж. Шмидт,