Bash - mudando o formato fileconfig

0

Eu gostaria de mudar:

ISTO:

client 192.168.100.1 {
    secret = ThisIStheSECRET
    shortname = HOSTNAME
}
client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}

QUE:

client HOSTNAME { secret = ThisIStheSECRET, ipaddr = 192.168.100.1 }
client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }

Como fazer isso? Quais ferramentas usar?

    
por Mario_bash 25.04.2018 / 14:46

4 respostas

1

Um script awk direto:

awk '
    /^client/               { ipaddr    = $2                              }
    /^[[:blank:]]*shortname/{ shortname = $3                              }
    /^[[:blank:]]*secret/   { secret    = $0; sub("^[^=]*= ", "", secret) }
    /^}/ {
        printf("client %s { secret = %s, ipaddr = %s }\n",
            shortname, secret, ipaddr);
    }' file

Simplesmente analise os bits de informação necessários quando os encontramos no arquivo de entrada, e quando atingimos um } no início de uma linha, geramos as informações coletadas no formato correto.

A análise do texto secret é especial, pois esperamos que ele contenha qualquer coisa , mesmo delimitadores de campo. Ele simplesmente começa definindo a variável secret para a linha inteira e, em seguida, exclui tudo até o primeiro = e o espaço único a partir de então.

Dado o arquivo

client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}
client 10.0.0.1 {
    secret =     This is it, the secret!, ipaddr = 10.0.0.1
    shortname = myhost.local
}

(observe quatro espaços no início do segredo), isso produz

client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }
client myhost.local { secret =     This is it, the secret!, ipaddr = 10.0.0.1, ipaddr = 10.0.0.1 }
    
por 25.04.2018 / 17:20
0

Tenho certeza de que há maneiras melhores de resolver isso, mas consegui isso com a seguinte combinação sed , awk .

sed ':a;N;$!ba;s/\n/ /g' file | sed -e 's/    //g' -e 's/ client/\nclient/' | awk '{print $1" "$9" "$3" "$4" "$5" "$6",  ipaddress "$8" "$2" "$10}'

Explicação

  • sed ':a;N;$!ba;s/\n/ /g' Para substituir todas as novas linhas por um espaço. Consulte esta esta resposta para mais informações
  • sed -e 's/ //g' Para substituir os quatro blocos espaçados por um único espaço.
  • -e 's/ client/\nclient/' Adicione a nova linha quando a sequência do cliente corresponder.
  • awk '{print $1" "$9" "$3" "$4" "$5" "$6", ipaddress "$8" "$2" "$10}' Awk por padrão delimita o texto com espaços, portanto, aqui você só precisa imprimir a variável de nome de host ($ 9) e a variável de endereço IP ($ 2) na ordem desejada. Você pode descartar a variável "shortname" ($ 7) e codificar o texto "ipaddress"

Espero que isso ajude você a conseguir o que deseja.

    
por 25.04.2018 / 16:50
0

Eu faria algo como:

perl -0777 -pe 's{client\s+(\S+)\s*\{\s*(secret = .*)\s+shortname\s*=\s*(.*)\s*\}}
                 {client $3 { $2, ipaddr = $1 }}g'
    
por 25.04.2018 / 16:55
0

Isso deve resolver seu problema, embora não seja tão "simples" quanto eu esperava:

perl -pe 's/(\w)\s*$/,\n/;' your_filename | perl -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/ }/g;'

Ele executa uma expressão regular para adicionar vírgulas às suas linhas que terminam com alfanuméricos (A a Z, a a z, 0 a 9 e _)

Ele executa outra expressão regular para substituir qualquer nova linha (e o espaço em branco em torno deles) por um espaço, a menos que essa linha termine em } (utilizando um look-behind negativo) e, finalmente, um regex para formatação final hostname e IP e remover vírgula estranha)

Isso ignora as novas linhas e você pode redirecionar o resultado para um novo arquivo (ou seu existente) com > your_new_filename adicionado ao final. Esta solução pode usar um sinalizador -i para modificá-lo se você fizer isso:

perl -i -pe 's/(\w)\s*$/,\n/;' your_filename
perl -i -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/ }/g;' your_filename
    
por 25.04.2018 / 15:17