
Я использую скрипты оболочки для настройки различных типов виртуальных машин. Часто эти скрипты включают многострочные переменные, которые необходимо вставить в файлы конфигурации в определенных позициях с помощью sed
.
Если я создам их вот так, то все будет хорошо:
VAR="Config Line1\nConfig Line2\nConfig Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
Однако это не делает сценарий очень читабельным, особенно с учетом того, что текстовые блоки могут быть довольно длинными.
Если я напишу их так:
VAR="Config Line1
Config Line2
Config Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
При запуске скрипта возникает ошибка: sed: -e expression #1, char 31: unknown command:
C'`
Есть ли способ использовать sed
переменные, объявленные таким образом?
решение1
Стандартный синтаксис команды a
:
sed -e 'a\
first line\
second line\
last line'
BSD (по крайней мере FreeBSD и OS/X) sed
удаляет начальные пробелы, инужно -e
обойти ошибку. GNU sed
позволяет переместить первую строку сразу после , a\
если она не пустая.
Итак, вам необходимо предварительно обработать входные данные:
VAR='content with
multiple lines
some with lead blanks
or even backslash\'
preprocessed_VAR=$(printf '%s\n' "$VAR" |
sed 's/\\/&&/g;s/^[[:blank:]]/\\&/;s/$/\\/')
sed -i -e "/MatchingPattern/a\\
${preprocessed_VAR%?}" somefile
(замените -i
на -i ''
во FreeBSD или OS/X).
В GNU/Linux и с оболочкой GNU ( bash
) или zsh
вместо этого вы можете сделать следующее:
sed -i '/MatchingPattern/r /dev/stdin' <<< "$VAR"
Это работает, потому что bash
и zsh
реализуются строки here с удаленными временными файлами, а /dev/stdin в Linux реализован как символическая ссылка на файл (что означает, что его можно открывать несколько раз, и каждый раз он будет открываться в начале).
Здесь вы также можете использовать GNU awk
:
(export VAR
gawk -i /usr/share/awk/inplace.awk '{print}; /MatchingPattern/{print ENVIRON["VAR"]}' somefile)
Не использовать-i inplace
as сначала gawk
пытается загрузить inplace
расширение (как inplace
или inplace.awk
) из текущего рабочего каталога, где кто-то мог разместить вредоносное ПО. Путь расширения, inplace
поставляемого с, gawk
может различаться в зависимости от системы, см. выводgawk 'BEGIN{print ENVIRON["AWKPATH"]}'
Или perl
(откуда это -i
):
(export VAR
perl -pi -e '$_ .= "$ENV{VAR}\n" if /MatchingPattern/' somefile)
решение2
Ошибка возникает из-за того, что sed
команде append a
требуется обратная косая черта после фактического a
:
С GNU sed
:
$ sed "/pattern/a\\$VAR" file.in >file.out
sed
Насколько мне известно, BSD может вставлять в файл с помощью этой a
команды только одну строку, если только символы новой строки не экранированы должным образом.
Близкий ответ о том, как решить эту проблему с помощью BSD sed
:http://unix.stackexchange.com/a/60322