Команда 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