Как поменять напильник на лету по трубе?
Я, вероятно, ищу способ буферизовать файл в начале канала, в отличие от этого:
cat foo.txt | grep bar > foo.txt
... сохранит входные данные от разрушения самой трубой. Есть в наличии такой буфер?
Попробуйте использовать губку из Moreutils как это:
sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd
Он собирает весь ввод перед записью на его вывод.
Я предполагаю, что sed все еще может создать временный файл, но следующее может сделать то, что вы хотите? (Использование strace может показать вам, создает ли sed временный файл или нет).
sed -i '/bar/!d' foo.txt
Восклицательный знак инвертирует совпадение, d означает удаление, поэтому удаляются все строки, в которых нет полосы.
Используйте >>, чтобы сохранить содержимое.
cat foo.txt | grep bar >> foo.txt
Теперь это будет добавлено в файл.
AFAIK, нет прямого способа добавить данные в файл в оболочке. Если вы хотите добавить в начало, вам может потребоваться использовать временный файл между ними.
В зависимости от того, насколько сложна ваша командная строка, вы можете сэкономить
cat foo.txt | grep bar | tee -a foo.txt
Лучший способ сделать это - вспомнить, как файлы работают в unix - файл существует до тех пор, пока есть ссылка на файл (каталог или процесс, открывающий файл).
Итак, откройте файл, удалите эту запись каталога, затем запустите процесс, который записывает в новую запись каталога с тем же именем, но связана с другим индексом.
Наконец, приятным моментом в этом является то, что он работает для любого типа конвейерной операции, а не только для того, что может взломать временный файловый буфер.
{ rm file ; sed -e s/this/that/g > file ; } < file
Небольшое предупреждение - это может привести к катастрофе, если вам нужно, чтобы перезапись была атомарной операцией. unix не предлагает чистых способов блокировки файлов, особенно на уровне оболочки. Это было проблемой в темные века, если вы делали что-то вроде редактирования файла паролей в загруженной системе, в которой работало что-то вроде NIS. Каждый раз, когда более одного процесса читают / записывают в файл, будьте очень осторожны, если ваша система занята или важна.
Единственные операции, которые со 100% уверенностью будут атомарными, - это манипуляции с записями каталога - rm / ln / mv (в той же файловой системе).
Так что теперь все становится длиннее и уродливее ...
Для математической части этого требуется оболочка posix или аналогичная расширенная оболочка Борна.
c=0
while
f=$SECONDS
test -f file.$c.tmp
do
c=$(($c+1))
done
grep stuff < file > file.$c.tmp && mv file.$c.tmp file
Ой, UUOC, бесполезное использование кота :) вам не нужен кот:
grep something somefile > someotherfile
Как сказал секенре, есть губка. Или, может быть, вы захотите попробовать встроенную версию perl (переключатель -i):
печатать только соответствующий вывод:
perl -ni -e 'm / foo / g и напечатать' bar.txt
замените "foo" на "bar" в файле:
perl -pi -e 's / foo / bar / g' bar.txt