Команда sed создает случайно названные файлы

Недавно я написал script, который выполняет команду sed, чтобы заменить все вхождения "string1" на "string2" в файле с именем "test.txt".

Он выглядит следующим образом:

sed -i 's/string1/string2/g' test.txt

Ловушка: "string1" необязательно существует в test.txt.

Я заметил, что после выполнения команды этих sed, я получаю несколько пустых файлов, оставшихся в каталоге, с именами, которые выглядят следующим образом:

"sed4l4DpD"

Кто-нибудь знает, почему это возможно, и как я могу его исправить?

Ответ 1

Итак, после большого тестирования прошлой ночью выяснилось, что sed создавал эти файлы при попытке работать с пустой строкой. Способ, которым я получал массив аргументов "$ string1", был через команду grep, которая, похоже, была неверной. То, что я хотел от grep, это все строки, содержащие что-то типа "Текст здесь". ".

Например, строка, "Text here 'ABC.DEF'" в файле, должна быть захвачена grep, а затем строка ABC.DEF строки будет заменена на ABC_DEF. К сожалению, grep, который я использовал, будет ловить строки типа "Text here ''" (то есть ничего между "'). Когда позже script попытался выполнить замену sed с использованием этой пустой строки, был создан случайный файл (вероятно, потому, что sed умер).

Спасибо за вашу помощь в понимании того, как работает sed.

Ответ 2

Я не смог воспроизвести это с помощью быстрого теста (используя GNU sed 4.2.1), но strace действительно показывал sed, создавая файл с именем sedJd9Cuy, а затем переименовывая его в tmp (файл с именем on командной строки).

Похоже, что что-то происходит неправильно после того, как sed создает временный файл и прежде чем он сможет его переименовать.

Моя лучшая догадка заключается в том, что у вас закончилась нехватка места в файловой системе; вы можете создать новый пустой файл, но не можете его записать.

Что говорит df .?

ИЗМЕНИТЬ

Я все еще не знаю, что вызывает проблему, но работать с ней не должно быть слишком сложно.

Вместо

sed -i 's/string1/string2/g' test.txt

попробуйте что-то вроде этого:

sed 's/string1/string2/g' test.txt > test.txt.$$ && mv -f test.txt.$$ test.txt

Что-то не так с тем, как sed создает, а затем переименовывает текстовый файл для замены исходного файла. Вышеприведенная команда использует sed как простой фильтр ввода-вывода и создает и переименовывает временный файл отдельно.

Ответ 3

-i - это суффикс, присвоенный новому/выходному файлу. Кроме того, для команды вам потребуется -e.
Вот как вы его используете:

sed -i '2' -e 's/string1/string2/g' test.txt

Это создаст файл под названием test.txt2, который является резервной копией test.txt

Чтобы заменить файл (вместо создания новой копии - подменю "на месте" ), измените значение -i на '' (т.е. пустое):

sed -i '' -e 's/string1/string2/g' test.txt

EDIT II

Здесь отображается фактическая строка командной строки с Mac (Snow Leopard), которая показывает, что мой измененный ответ (удаленное пространство между -i и суффиксом) является правильным.
ПРИМЕЧАНИЕ. На сервере linux между ним не должно быть пробела -i и суффикса.

> echo "this is a test" > test.txt
> cat test.txt
this is a test
> sed -i '2' -e 's/a/a good/' test.txt 
> ls test*
test.txt    test.txt2
> cat test.txt
this is a good test
> cat test.txt2
this is a test
> sed -i '' -e 's/a/a really/' test.txt 
> ls test*
test.txt    test.txt2
> cat test.txt
this is a really good test

Ответ 4

Лучше, если вы сделаете это следующим образом:

cat large_file | sed 's/string1/string2/g' > file_filtred