Ответ 1
Так как утилита ed больше не получает достаточного внимания:
a=5.3827
ed -s poscar1.cif <<EOF
g/^_cell_length_a\$/ s//& $a/
w
EOF
ed
действительно редактирует файл на месте, в отличие от sed
с его опцией -i
[1].
sed
заимствовал множество функций от ed
, поэтому существует существенное перекрытие функциональности, но есть также важные отличия, некоторые из которых здесь.
-
-s
подавляет сообщения о статусеed
. -
poscar1.cif
- это входной файл для редактирования на месте. -
<<EOF ...
- здесь-документ, который содержит команды дляed
-ed
, требует, чтобы его команды поступали из stdin и каждая команда должна быть в отдельной строке. -
g/^_cell_length_a\$/
... является (базовым) регулярным выражением (регулярным выражением), которое соответствует всем строкам, содержащим_cell_length_a
-g
, чтобы не сообщалось об ошибке, если совпадение вообще отсутствует.- Обратите внимание, что
$
является\
-escaped, чтобы защитить его от интерпретации оболочкой внутри этого документа (не обязательно в этом случае, но хорошей практикой).
- Обратите внимание, что
-
s//& $a/
...//
повторяет поиск последнего используемого регулярного выражения в соответствующей строке и заменяет совпадение с самим собой (&
), за которым следует пробел и значение переменной$a
.- Обратите внимание, что, поскольку открывающий разделитель (
EOF
) здесь-документа некотируется, происходит разложение переменных оболочки DO; по сути, содержимое обрабатывается оболочкой подобно содержимому строки с двумя кавычками.
- Обратите внимание, что, поскольку открывающий разделитель (
-
w
записывает измененный буфер обратно во входной файл.- Для отладки используйте
,p
вместоw
, чтобы печатать только модифицированный буфер, не записывая его обратно в файл.
- Для отладки используйте
[1] Обновление на месте:
Точнее, ed
сохраняет существующий файл inode, что гарантирует сохранение всех атрибутов файла.
Однако он не перезаписывает отдельные байты существующего файла, но считывает весь файл в буфер в памяти и записывает весь буфер в файл при его запросе.
Это делает ed
пригодным только для файлов, достаточно малых для чтения в памяти в целом.
В отличие от sed -i
(GNU и BSD sed
), его аналог GNU 4.1 +, awk -i inplace
, а также perl -i
заменить исходный файл на новый, что означает, что они:
- уничтожить символические ссылки (!) - если входной файл был символической ссылкой, он заменяется обычным файлом с тем же именем
- Общий сценарий, в котором это имеет значение: скажем, файл инициализации вашей оболочки
~/.bashrc
является символической ссылкой на файл в другом месте, который вы держите под контролем источника; затем вы устанавливаете инструмент, который используетsed -i
для изменения~/.bashrc
, в результате чего он заменяется обычным файлом, и ссылка на вашу версию с контролируемым источником не работает. - Что еще, поведение BSD
sed
даже представляет угрозу безопасности (см. ниже).
- Общий сценарий, в котором это имеет значение: скажем, файл инициализации вашей оболочки
- do не сохранить дату создания файла (если поддерживается, например, в OSX)
-
они делают, однако
- сохранить расширенные атрибуты (если поддерживается, например, в OSX)
-
сохранить файлы разрешений
- Внимание: BSD
sed
представляет риск безопасности по отношению к символическим ссылкам (поведение по-прежнему присутствует в версии версии FreeBSD 10):- Разрешения symlink копируются в файл замены, а не в цель symlink. Поскольку symlinks получает исполняемые разрешения по умолчанию, , вы всегда будете иметь исполняемый файл, независимо от того, был ли входной файл исполняемым или нет.
- К счастью, GNU
sed
корректно обрабатывает этот сценарий.
- Внимание: BSD
sed
, gawk
и perl
могли бы устранить проблемы выше, выполнив дополнительные шаги, но там одна вещь, которая может быть обеспечена только в том случае, если исходный индекс сохраняется, а ed
выполняет
Когда файл отслеживается для изменений по его номеру inode (например, с tail -f
), не сохраняя разрывы inode, которые контролируют.