
Eu uso scripts de shell para configurar diferentes tipos de VMs. Freqüentemente, esses scripts incluem variáveis multilinhas que precisam ser inseridas em arquivos de configuração em determinadas posições usando sed
.
Se eu criá-los assim, está tudo bem:
VAR="Config Line1\nConfig Line2\nConfig Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
Isso não torna o script muito legível, especialmente porque os blocos de texto podem ser bastante longos.
Se eu escrevê-los assim:
VAR="Config Line1
Config Line2
Config Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
Recebo um erro ao executar o script: sed: -e expression #1, char 31: unknown command:
C'`
Existe uma maneira de usar sed
com variáveis declaradas assim?
Responder1
A sintaxe padrão do a
comando é:
sed -e 'a\
first line\
second line\
last line'
BSD (pelo menos FreeBSD e OS/X) sed
remove os espaços em branco iniciais, eprecisa do -e
para solucionar um bug. GNU sed
permite mover a primeira linha para logo após, a\
desde que não esteja vazia.
Então, você precisaria pré-processar a entrada:
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
(substitua -i
por -i ''
no FreeBSD ou OS/X).
No GNU/Linux e com o shell GNU ( bash
) ou zsh
, você pode fazer:
sed -i '/MatchingPattern/r /dev/stdin' <<< "$VAR"
Isso funciona porque bash
implementa zsh
here-strings com arquivos temporários excluídos e /dev/stdin no Linux é implementado como um link simbólico para o arquivo (o que significa que ele pode ser aberto várias vezes e, a cada vez, é aberto no início).
Aqui você também pode usar o GNU awk
:
(export VAR
gawk -i /usr/share/awk/inplace.awk '{print}; /MatchingPattern/{print ENVIRON["VAR"]}' somefile)
Não use-i inplace
as gawk
tenta carregar primeiro a inplace
extensão (como inplace
ou inplace.awk
) do diretório de trabalho atual, onde alguém poderia ter plantado malware. O caminho da inplace
extensão fornecida gawk
pode variar de acordo com o sistema, consulte a saída degawk 'BEGIN{print ENVIRON["AWKPATH"]}'
Ou perl
(de onde isso -i
vem):
(export VAR
perl -pi -e '$_ .= "$ENV{VAR}\n" if /MatchingPattern/' somefile)
Responder2
O erro ocorre porque o sed
comando de acréscimo a
precisa de uma barra invertida após o real a
:
Com GNU sed
:
$ sed "/pattern/a\\$VAR" file.in >file.out
BSD sed
, até onde eu sei, só é capaz de inserir uma única linha em um arquivo com o a
comando, a menos que as novas linhas sejam escapadas corretamente.
Resposta intimamente relacionada sobre como resolver isso com BSD sed
:http://unix.stackexchange.com/a/60322