Usando sed no shell script com variáveis multilinhas

1

Eu uso scripts shell para configurar diferentes tipos de VMs. Geralmente, esses scripts incluem variáveis multilinhas que precisam ser inseridas nos 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

Eu 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?

    
por tylero 15.12.2016 / 16:15

2 respostas

2

A sintaxe padrão para o comando a é:

sed -e 'a\
first line\
  second line\
last line'

BSD (pelo menos FreeBSD e OS / X) sed retira os espaços em branco à esquerda e precisa do -e para contornar um bug . O GNU sed permite mover a primeira linha para a direita após o 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 isso:

sed -i '/MatchingPattern/r /dev/stdin' <<< "$VAR"

Isso funciona porque bash e zsh implementam strings aqui 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 sempre , está aberto no começo).

Aqui você também pode usar o GNU awk :

(export VAR
gawk -i inplace '{print}; /MatchingPattern/{print ENVIRON["VAR"]}' somefile)

Ou perl (de onde vem esse -i ):

(export VAR
perl -pi -e '$_ .= "$ENV{VAR}\n" if /MatchingPattern/' somefile)
    
por 07.09.2017 / 16:13
0

O erro é devido ao comando sed append a que precisa de uma barra invertida após o% reala:

Com o GNU sed :

$ sed "/pattern/a\$VAR" file.in >file.out

O BSD sed é, até onde eu sei, apenas capaz de inserir uma única linha em um arquivo com o comando a , a menos que as novas linhas sejam corretamente escapadas.

Resposta próxima de como resolver isso com o BSD sed : link

    
por 07.09.2017 / 15:44