Потоковое редактирование на месте с помощью ed


ramok аватар

ramok - Posted on 07 Апрель 2010

Для того что бы заменить строчку в файле часто используется sed с ключиком -i.
Но не все знают что sed на самом деле создает копию файла и заменяет его на оригинал (не лишнее будет прочитать в man sed что на самом деле обозначает -i).
Проверить это можно так:

$ echo 1 > z.txt && ls -li z.txt && sed -i 'i1' z.txt && ls -li z.txt && rm z.txt
5290353 -rw-rw-r-- 1 ramok ramok 2 Апр  7 13:00 z.txt
5290354 -rw-rw-r-- 1 ramok ramok 4 Апр  7 13:00 z.txt

Здесь создается пустой текстовый файл, выводится номер его inode, затем с помощью sed добавляется '1', и снова выводится inode файла.
Видно что inode изменился.
При этом копия файла создается в текущей директории. Увидеть это можно так:

$ echo 1 > z.txt && ls -li z.txt && strace sed -i 'i1' z.txt 2>&1 | grep open && ls -li z.txt && rm z.txt
879149 -rw-rw-r-- 1 komar komar 2 Апр  7 13:06 z.txt
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/libselinux.so.1", O_RDONLY)  = 3
open("/lib/i686/cmov/libc.so.6", O_RDONLY) = 3
open("/lib/i686/cmov/libdl.so.2", O_RDONLY) = 3
open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
open("//lib/charset.alias", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = 3
open("z.txt", O_RDONLY|O_LARGEFILE)     = 3
open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 4
open("./sed3H2GOp", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4
5290353 -rw-rw-r-- 1 komar komar 4 Апр  7 13:06 z.txt

Это обозначает что иногда могу возникнуть проблемы если недостаточно места на диске для создания копии файла или вы не имеете право создавать файлы в текущей директории. Так же это не сработает если вы хотите изменить что то в виртуальных файлах в файловой системе /proc и /sys.
Так же если файл большой, то может существенно тормозить, что плохо подходит для больших лог файлов.

Поэтому не рекомендуется пользоватся sed таким образом. Хотя все это делают Ж:-)

Решение в лоб - создавать копию файла явно и затем заменять с проверкой все ли закончилось удачно.

Еще одно решение - использовать прорадителя sed, текстовый редактор ed.

$ echo 1 > z.txt && ls -li z.txt && ed -s z.txt <<<$'i\n1\n.\nwq\n' && ls -li z.txt && rm z.txt
5290353 -rw-rw-r-- 1 ramok ramok 2 Апр  7 13:00 z.txt
5290353 -rw-rw-r-- 1 ramok ramok 4 Апр  7 13:00 z.txt

Тут ed делает тоже самое что и sed в примере выше (добляет '1' после каждой строчки).
Видно что inode не изменился.

4.75
Ваша оценка: Ничего Рейтинг: 4.8 (4 голоса)

perl -p -i -e 's/чтоищем/начтоменяем/g' file
не проще ли?

а проверить не пробовал? не проще

$ echo 1 > z.txt && ls -li z.txt && perl -pi -e 'print "$_"' z.txt && ls -li z.txt && rm z.txt
5290359 -rw-rw-r-- 1 ramok ramok 2 Апр  8 19:32 z.txt
5290379 -rw-rw-r-- 1 ramok ramok 4 Апр  8 19:32 z.txt

таже песня что и с sed

Отправить комментарий

Google Friend Connect (leave a quick comment)
loading...
Содержание этого поля является приватным и не предназначено к показу.