1
$ cat test.txt
foo
bar

Эта команда sed заменяет первую строку в text.txt на "baz". Он отлично работает из командной строки:

$ sed "1s%.*%baz%" "test.txt" > "test.txt"
$ cat test.txt
baz
bar

Я хотел бы иметь возможность поместить эту команду sed в скрипт с именем test.sh следующим образом:

#!/bin/sh
sed "1s%.*%baz%" "test.txt" > "test.txt"

Но когда я запускаю ./test.sh он удаляет все строки из text.txt (text.txt полностью очищен)?!

Есть идеи?

1 ответ1

6

Вы не можете (безопасно) перенаправить вывод команды в файл, который она читает. Тебе "повезло", что это случилось из командной строки. Вероятно, в одном случае sed смог прочитать весь файл до того, как оболочка его забила, а в другом - нет. Разница, вероятно, связана с некоторой проблемой буферизации, но не стоит ее выяснять.

Если вы хотите изменить файл на месте, вы должны записать вывод во временный файл, а затем (если это удалось) переименовать временный файл в имя входного файла.

Например:

sed "1s%.*%baz%" test.txt > $$ && mv $$ test.txt

$$ - идентификатор процесса текущей оболочки; это удобный способ получить достаточно уникальное имя файла. Или вы можете использовать, скажем, test.txt.$$ или даже tmp если у вас нет чего-то с таким именем.

В конкретном случае команды sed вы можете использовать опцию -i чтобы изменить файл на месте, но это только заставит sed создать временный файл внутри. Синтаксис или даже существование, если опция -i может варьироваться от одной реализации sed к другой; проверьте вашу местную документацию.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .