Processe um arquivo de texto e crie um comando usando scripts de shell

0

Eu tenho um arquivo com nomes de servidor e domínio, conforme abaixo.

Names.txt:

ABCDomain ContractABCServer_1
ABCDomain ABC_server1
LinkDomain CoreLinkServer_1
TADDomain TADServer_1

(Eu estou ficando acima do arquivo depois de realizar operações de ordenação e exclusivas para algum outro arquivo.) --- apenas informações adicionais

Eu preciso extrair valores do arquivo acima e passá-lo para um comando xyz (o comando é usado para reiniciar servidores) como um parâmetro no formato abaixo.

O / P:

"ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"

Eu estou usando a lógica abaixo indicada, mas não me dá a saída desejada, pois o DomainName tem que vir apenas uma vez para cada conjunto. Também estou tendo problemas em manter a mesma linha.

----------- START ------

    DOMAIN=''

IFS=' '
while read line
do
        DOMAIN=$(echo "$line" | awk -F " " '{print $1}')

        for word in $line
        do
                if [[ "$word" == "$DOMAIN" ]]; then
                        Server=$(echo "$line" | awk -F " " '{print $2}' )
                        echo -n "(server:$ServerName"
                fi

        done

done < Names.txt
    
por Aditya Telang 19.06.2018 / 11:45

4 respostas

0
{
    if (dom[$1]) 
        dom[$1]=dom[$1]","$2
    else 
        dom[$1]=$2
} 

END {
    ORS=",";
    for (d in dom)
        if (d)
            print ("\""d"(server:"dom[d]")""\"")
}

Esta é uma solução awk rápida e suja. Salve-o como algo.awk e execute:

awk -f something.awk Names.txt 

Uma solução rápida em resposta a sua comentário :

{ dom[$1]=dom[$1] ? dom[$1]",server:"$2 : "server:"$2 }

END {
    for (d in dom)
        if (d) {
            out && out = out","
            out = out"\""d"("dom[d]")""\""
        }
        print out
}
    
por 19.06.2018 / 14:31
0

Você pode montar as strings separadas por vírgula diretamente em awk e imprimir o composto no final:

  $1 == "ABCDomain"  {d = (d == "") ? $2 : d "," $2; next} 
  $1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next} 
  $1 == "TADDomain"  {t = (t == "") ? $2 : t "," $2; next} 

  END {
    printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
  }

Ex.

$ awk '
  $1 == "ABCDomain"  {d = (d == "") ? $2 : d "," $2; next} 
  $1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next} 
  $1 == "TADDomain"  {t = (t == "") ? $2 : t "," $2; next} 

  END {
    printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
  }' Names.txt
"ABCDomain(server:ContractABCServer_1,ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
    
por 19.06.2018 / 14:29
0

Você pode usar este código, leia o código antes de executá-lo, pois ele está criando um diretório na pasta /tmp chamada domains e, em seguida, removendo-o no final

 DOMAIN=''

    IFS=' '
    declare -A domain
    mkdir /tmp/domains
    while read line
    do
            DOMAIN=$(echo $line | awk  '{print $1}')
            SERVER=$(echo $line | awk '{print $2}' )
            echo "$SERVER," >> /tmp/domains/$DOMAIN
            domain[$DOMAIN]=1
    done < Names.txt

    sed -ir "$ s/.,$//" /tmp/domains/*

    for i in "${!domain[@]}"; do
             echo -n "$i(server:";
             while read line ; do
                 echo -n "$line" ;
             done < /tmp/domains/$i
             echo ")"
    done
    rm -rf /tmp/domains

Isto está criando uma pasta na pasta / tmp com os seguintes dados, de modo que cada nome de arquivo do domínio tenha uma lista de servidores contidos neles

$ ls -lhtr /tmp/domains/
total 12K
-rw-rw-r-- 1 arushirai arushirai 11 Jun 19 17:54 TADDomain
-rw-rw-r-- 1 arushirai arushirai 16 Jun 19 17:54 LinkDomain
-rw-rw-r-- 1 arushirai arushirai 32 Jun 19 17:54 ABCDomain

$ cat /tmp/domains/ABCDomain 
ContractABCServer_1,
ABC_server
$ cat /tmp/domains/LinkDomain 
CoreLinkServer_
$ cat /tmp/domains/TADDomain 
TADServer_
    
por 19.06.2018 / 14:23
0

(Atualizado para corrigir o formato de saída)

Usando awk :

BEGIN { OFS = "," }

{ servers[$1] = (servers[$1] == "" ? "server:" $2 : servers[$1] "," "server:" $2 ) }

END {
    $0 = ""
    for (domain in servers)
        $(++n) = sprintf("\"%s(%s)\"", domain, servers[domain])

    print
}

Isso adicionaria os servidores como uma string delimitada por vírgula ao domínio específico no bloco principal durante a análise do arquivo de entrada. Isso é feito modificando a matriz servers que contém os servidores de um domínio específico (o domínio é a chave na matriz).

No bloco END , fazemos o loop de todas as chaves / domínios na matriz servers e criamos um registro de saída no formato especificado.

Executando isso nos dados fornecidos:

$ awk -f script.awk names.txt
"TADDomain(server:TADServer_1)","ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)"

Um script bash em grande parte equivalente (requer bash 4,3+ para o array associativo):

declare -A servers

while read domain server; do
    servers[$domain]+="${servers[$domain]:+,}server:$server"
done <names.txt

for domain in "${!servers[@]}"; do
    out+="${out:+,}\"$domain(${servers[$domain]})\""
done

printf '%s\n' "$out"

... mas veja " Por que usar um loop de shell para processar texto considerado uma prática ruim? ".

    
por 19.06.2018 / 15:00