Как запустить команду sed с помощью ввода и вывода в виде одного и того же файла?
Я пытаюсь использовать команду sed в оболочке script, где я хочу удалить строки, которые читают STARTremoveThisComment
, и строки, которые читают removeThisCommentEND
.
Я могу сделать это, когда я скопирую его в новый файл, используя
sed 's/STARTremoveThisComment//' > test
Но как это сделать, используя тот же файл, что и вход и выход?
Ответы
Ответ 1
sed -i
(или расширенная версия, --in-place
) автоматизирует процесс, обычно выполняемый с использованием менее продвинутых реализаций, который отправляет вывод во временный файл, а затем переименовывает его обратно в оригинал.
-i
предназначен для редактирования на месте, и вы также можете предоставить суффикс резервного копирования для хранения копии оригинала:
sed -i.bak fileToChange
sed --in-place=.bak fileToChange
Оба из них сохранят исходный файл в fileToChange.bak
.
Имейте в виду, что редактирование на месте не может быть доступно во всех реализациях sed
, но оно находится в GNU sed
, которое должно быть доступно для всех вариантов Linux в соответствии с вашими тегами.
Если вы используете более примитивную реализацию, вы можете использовать что-то вроде:
sed 'whatever' oldfile >newfile ; mv newfile oldfile
хотя некоторые проверки ошибок были бы приятными.
Ответ 2
Вы можете использовать флаг -i для редактирования на месте и -e для указания обычного выражения script:
sed -i -e 's/pattern_to_search/text_to_replace/' file.txt
Чтобы удалить строки, соответствующие определенному шаблону, вы можете использовать более простой синтаксис. Обратите внимание на флаг d:
sed -i '/pattern_to_search/d' file.txt
Ответ 3
Вы действительно не должны использовать sed для этого. Этот вопрос, кажется, возникает довольно часто, и это кажется очень странным, так как общее решение настолько тривиально, что кажется странным, что люди хотят знать, как это сделать в sed, и в python, и в ruby, и т.д. Если вы хотите, чтобы фильтр работал на входе и перезаписывал его, используйте следующий простой script:
#!/bin/sh -e
in=${1?No input file specified}
mv $in ${bak=.$in.bak}
shift
"[email protected]" < $bak > $in
Поместите это в свой путь в имя исполняемого файла inline
, а затем проблема будет решена в целом. Например:
inline input-file sed -e s/foo/bar/g
Теперь, если вы хотите добавить логику для сохранения нескольких резервных копий или если у вас есть некоторые опции для изменения схемы именования резервных копий или что-то еще, вы можете исправить ее в одном месте. Какая опция командной строки получает 1-up счетчики в файле резервной копии при обработке файла на месте с помощью perl
? Как насчет ruby
? Опция отличается от gnu-sed
? Как awk
справится с этим? Целая точка unix - это то, что инструменты делают только одно. Обработка логики для файлов резервных копий - это вторая вещь, и ее необходимо учесть. Если вы реализуете инструмент, не добавляйте логику для создания файлов резервных копий. Попросите пользователей использовать для этого 2-й инструмент. Интеграция плохая. Модульность хорошая. Это путь unix.
Обратите внимание, что этот script имеет несколько проблем. Например, разрешения/режим входного файла могут быть изменены. Я уверен, что есть и другие проблемы. Однако, поместив логику резервного копирования в оболочку script, вы локализуете все эти проблемы и не должны беспокоиться о том, что sed
перезаписывает файлы и режим изменений, а python
сохраняет файл на месте и не выполняет измените индексный дескриптор (я составил эти два случая, в том случае, если не все инструменты будут использовать одну и ту же логику, а оболочка script будет.)
Ответ 4
Насколько я знаю, невозможно использовать один и тот же файл для ввода и вывода. Хотя одно из решений делает оболочку script, которая сохранит ее в другом файле, удалит старый вход и переименует вывод в имя входного файла.
sed -e s/try/this/g input.file > output.file;mv output.file input.file
Ответ 5
Я предлагаю использовать sponge
Губка читает стандартный ввод и записывает его в указанный файл. В отличие от перенаправления оболочки, губка впитывает весь свой ввод перед записью выходного файла. Это позволяет создавать конвейеры, которые читают и пишут в один и тот же файл.
cat test | sed 's/STARTremoveThisComment//' | sponge test