Назад | Перейти на главную страницу

Изменение файлов на лету в Linux (запись во входной файл по конвейеру)

Как поменять напильник на лету по трубе?

Я, вероятно, ищу способ буферизовать файл в начале канала, в отличие от этого:

    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