Combinação, Inserção e Exclusão de Padrão de Sequência de Várias Linhas com sed ou awk

1

Estou tentando escrever um script para atualizar automaticamente meu .ssh/config . Basicamente, é uma ferramenta de gerenciamento ssh que adiciona uma entrada .ssh/config para um computador de entrada, usuário, etc.

Pergunta:

Existe alguma ferramenta disponível (como sed , ou awk ) para inserir ou remover automaticamente todas as instâncias de strings multi-line ?

Por exemplo, com o comando sed :

# inserts "stuff" in the line above "single-line-pattern" in file
sed -i.bkp "/single-line-pattern/i stuff" file

# inserts "stuff" in the line below "single-line-pattern" in file
sed -i.bkp "/single-line-pattern/a stuff" file

# removes all instances of "single-line-pattern" from file
sed -i.bkp "/single-line-pattern/d" file

Trabalho possível ao redor

Uma solução alternativa hacky para excluir todas as instâncias de padrão é inverter o problema e localizar todas as não instâncias, imprimi-las em um novo arquivo e excluir o arquivo antigo. Ignorando anexando acima de uma entrada (porque eu deletei todos eles) eu apenas acrescentar ao final do arquivo em uma ordem fixa.

Dito isto, isto não responde à pergunta acima, ou dá exemplos de tais ferramentas ou sed / awk funções que trabalham com strings multi-line .

Minha solução

O script hacky que funciona para mim é fornecido abaixo. Você notará que eu uso awk e lida bem com o problema de várias linhas. É só que, até onde eu sei, awk não fornece muitas ferramentas para manipular ou contornar essa frase como os exemplos sed dados acima.

# create backup of file
cp $FILE $FILE.bak

# delete previous .tmp file
if [ -f $FILE.tmp ]; then
    rm $FILE.tmp
fi

# if the expression is not in the paragraph, append it to $FILE.tmp
awk -v RS="" -v expr1="Host $COMPUTER" -v expr2="Match originalhost \
$COMPUTER" -v user="User $USER" \
'{ if (! (($0 ~ expr1 || $0 ~ expr2) && $0 ~ user)) print$0 "\n"}' \
$FILE >> $FILE.tmp

mv $FILE.tmp $FILE

Meu espaço para problemas

Um conjunto de parágrafos em $FILE para $COMPUTER="compy" e $USER="harpo" é dado abaixo. Pode-se imaginar entradas para outros computadores ou mesmo para outros usuários no mesmo computador (verificando, portanto, as correspondências COMPUTER e USER).

Match originalhost compy exec /usr/local/bin/superscript.sh
   HostName 192.168.0.101
   User harpo
   Port 22
   IdentityFile /home/harpo/.ssh/id_rsa

Host compy
   HostName 123.123.123.123
   User harpo
   Port 33
   IdentityFile /home/harpo/.ssh/id_rsa
    
por RACKGNOME 04.03.2018 / 17:32

1 resposta

0

Que tal colocar um símbolo de comentário entre cada parágrafo e garantir que nenhum outro símbolo de comentário exista no arquivo. Então você pode usar awk e definir RS="#" para ter awk lendo um parágrafo inteiro como um único registro, você pode fazer o seu processamento e verificação, e então você pode produzir (ou não) o que você quer, como você quer , depois ou depois no arquivo ou no final do arquivo (usando o especificador de endereço END de awk ).

UPDATE: A documentação de awk informa que, para esta resposta funcionar, não há razão para exigir que os símbolos de comentário não existam em outro lugar no arquivo, porque o valor de RS pode ser um regex!

    
por 05.03.2018 / 03:29