Como criar uma lista de itens sob títulos específicos em um documento de texto? (Linux / Bash)

1

Coloque o mais simples possível, no Linux com bash / sed / awk e comandos básicos do sistema operacional, estou tentando criar uma lista com vários títulos em um arquivo de texto, com um monte de seqüências de caracteres abaixo deles (nomes de servidores). Espero, então, poder ter um script para executar várias tarefas em cada uma das entradas sob um cabeçalho específico que eu passe como uma opção / parâmetro em tempo de execução.

Exemplo de como seria esse arquivo de texto: (essas entradas devem ser ordenadas sob o cabeçalho em questão em uma única coluna, não consigo exibir dessa maneira nesta página.)

[main_server_list]
Jupiter
Saturn
Thisguy
Thatguy
BuffalO
randomspite
coffeebinge

[alternate_server_list]
Jupiter
Saturn

[Tertiary_server_list]
Thisguy
Thatguy
coffeebinge

[Enough_already]
BuffalO
randomspite

Então, basicamente, se eu quisesse copiar um arquivo para um diretório em TODAS as minhas máquinas, eu gostaria de fazer algo como:

   # bash maincopyscript.sh [main_server_list]

E o "loop" saberia que a lista de servidores para instalar isso seria toda entrada sob o cabeçalho [main_server_list], mas ignoraria todo o resto sob qualquer outro cabeçalho.

Da mesma forma, também quero ser capaz de fazer:

   # bash maincopyscript.sh [Tertiary_server_list]

E espere a mesma funcionalidade, só que desta vez, só execute o "loop" nas entradas sob o cabeçalho [Tertiary_server_list], e então termine.

Por fim, gostaria de poder especificar vários cabeçalhos, se desejar, especificado em qualquer ordem. Tais como:

   # bash maincopyscript.sh [Enough_already] [alternate_server_list]

Em seguida, ele deve executar as operações especificadas no script apenas nas entradas nesses dois cabeçalhos e, em seguida, ser concluído.

Espero que você tenha a ideia, basicamente uma maneira de fazer isso utilizando principalmente o bash / sed / awk. (ou até mesmo outra ferramenta, se necessário)

Sim, eu entendo que o ansible / puppet / chef também pode me ajudar a alcançar esses resultados, mas tenho motivos específicos para querer fazer isso independentemente. Eu tentei procurar por uma hora ou 2 para qualquer post pré-existente sobre isso, mas não consegui encontrar um, então finalmente decidi fazer a minha pergunta. Qualquer ajuda seria apreciada!

(Bônus, se alguém puder me mostrar como colocar as entradas em cada cabeçalho em ordem alfabética, mantendo os cabeçalhos e grupos nas mesmas formações que seriam ótimas também!)

    
por Viscosity 09.08.2016 / 17:29

1 resposta

1

Você pode puxar os nomes de um título com, digamos, awk e lançá-los em um array variável , em seguida, repita a matriz com for . O script aqui pega o padrão da linha de comando.

#!/bin/bash
patt=$1
if [ -z "$patt" ] ; then echo "need an argument" ; exit 1 ; fi
A=( $(awk '/^\[/ {p = 0};
           /^\['"$patt"'\]/ {p=1; next}
           p && !/^ *$/ ;' < servers )  )

for x in "${A[@]}" ; do 
    echo doing something with "$x" 
done

Então,

$ bash for_all.sh alternate_server_list
doing something with Jupiter
doing something with Saturn

No programa awk :
/^\[/ {p = 0} - defina p para zero se um colchete aberto for o primeiro caractere na linha,% /^\['"$patt"'\]/ {p=1; next} - se correspondermos ao padrão, defina p para um e pule para a próxima linha. Note que o padrão é dado ao awk a partir da variável shell, então será tomado como uma expressão regular. As citações são um pouco engraçadas, porque há parte do código entre aspas simples, depois a variável entre aspas duplas e, em seguida, mais código entre aspas simples. como 'foo' "$var" 'bar' , mas sem os espaços.
p && !/^ *$/ - se p estiver definido e a linha não estiver vazia (apenas espaços entre o início e o fim), imprima-a (ação padrão).

Ah, e isso irá falhar se os itens da sua lista contiverem algo engraçado, como espaços.

    
por 09.08.2016 / 18:02