converte tabela para arquivo ini usando matrizes bash

5

Eu tenho um desafio para pegar um arquivo de saída ("inventory.list") neste formato:

hostname1.env1.domain   | abc  | environment1
hostname2.env1.domain   | abc  | environment1
hostname3.env2.domain   | abc  | environment2
hostname4.env2.domain   | abc  | environment2
hostname5.env1.domain   | def  | environment1
hostname6.env2.domain   | def  | environment2
(6 rows)

e escreva em outro arquivo em um formato diferente:

[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain

[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain

[def.environment1]
hostname5.env1.domain

[def.environment2]
hostname6.env2.domain

abc e def são funções atribuídas a servidores e pode haver vários servidores para cada função, bem como funções com o mesmo nome, mas em ambientes diferentes. Eu tenho que dividir cada nome de host em grupos exclusivos de [role.environment] e, adicionalmente, excluir completamente a linha final do arquivo que é uma contagem de linha (este arquivo é uma saída de uma consulta sql).

Eu posso ler o arquivo, remover os canais e os espaços em branco e atribuir / exibir os agrupamentos de função / ambiente, sem problemas:

#! /bin/bash
while IFS='| ' read -r certname role env; do
  printf '%s\n' "[""$role"".""$env""]"
done < "/tmp/inventory.list"

... que me fornece os nomes dos grupos de papéis / ambientes:

[abc.environment1]
[abc.environment2]
[def.environment1]
[def.environment2]

mas não consigo descobrir como imprimir os nomes de host vinculados a cada grupo de função / ambiente abaixo do nome de cada grupo, nem posso descobrir como fazer com que meu script ignore a linha de contagem da última linha. Eu estou supondo que eu tenho que atribuir ainda mais o meu papel e campos de ambiente (segundo e terceiro campos) para sua própria matriz para, em seguida, referir a ele para pegar os nomes de host ligados a cada agrupamento exclusivo, mas não tenho idéia de como conseguir isso. Alguém pode aconselhar, por favor?

    
por HelenH 12.01.2016 / 14:27

4 respostas

5

Use uma matriz associativa para armazenar os nomes dos certificados por função e ambiente.

#! /bin/bash

unset -v envs
declare -A envs

while IFS='| ' read -r certname role env; do
    envs["$role.$env"]+="$certname"$'\n' 
done < /tmp/inventory.list

for e in "${!envs[@]}" ; do
    printf '%s\n' "[$e]" "${envs[$e]}"
done

Para classificar as seções, você pode imprimir as chaves, classificá-las e, em seguida, lê-las novamente e exibir os valores associados:

for e in "${!envs[@]}" ; do
    printf '%s\n' "$e"
done | sort | while read -r e ; do
    printf '%s\n' "[$e]" "${envs[$e]}"
done
    
por 12.01.2016 / 14:42
6

Eu usaria um utilitário de texto para processar texto em vez de usar um loop de shell para processar texto (embora aqui, IFS=' |' está bem adaptado ao seu caso). Como:

awk -F ' *[|] *' '
  NF == 3 {host[$2"."$3] = host[$2"."$3] $1 "\n"}
  END{for (i in host) print "[" i "]\n" host[i]}' < file

Observe que a ordem das entradas não é garantida. Com o% GNUawk, adicione um BEGIN{PROCINFO["sorted_in"] = "@ind_str_asc"} para classificar com base nas chaves.

Dependendo de qual RDBMS você está usando, você também pode exibi-lo no formato correto (como GROUP_CONCAT em mysql ou string_agg em postgre ).

Para começar, você provavelmente também poderia pedir ao seu utilitário de consulta RDBMS para formatar a saída em um formato mais adequado para o pós-processamento (cabeçalhos de tira, rodapés e usar valores separados por guias, por exemplo).

    
por 12.01.2016 / 14:43
2

Perl magic:

$ perl -lne '@F=split(/\s*\|\s*/); push @{$k{"$F[1].$F[2]"}},$F[0]; 
     END{foreach (keys(%k)){print "[$_]"; print join "\n",@{$k{$_}}} }' file
[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain
[def.environment1]
hostname5.env1.domain
[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain
[def.environment2]
hostname6.env2.domain
    
por 12.01.2016 / 14:46
2

Uma maneira de usar o awk:

$ sed 's/ //g' file | awk -F"|" '{x="["$2"."$3"]";}!(x in a){print x;a[x];}{print $1}'
    
por 12.01.2016 / 14:46