Mesclar colunas e adicionar

2

Eu tenho um arquivo com o seguinte conteúdo (há espaços adicionais para preencher a primeira coluna)

  1 account1 192.168.0.1  
  1 account1 192.168.0.2   
 19 account2 192.168.0.1   
100 account3 192.168.0.3   
  1 account3 192.168.0.5

Estou tentando obter uma saída de

  2 account1 192.168.0.1, 192.168.0.2  
 19 account2 192.168.0.1  
101 account3 192.168.0.3, 192.168.0.5   

que eu vou percorrer para que eu possa criar uma tabela html para enviar por e-mail para uma conta. Consegui obter a lista de IPs por conta usando:

awk '{a[$2]=a[$2]" " $3}END{for (i in a) print i" " a[i]}' inputfile

mas também não consigo resumir a primeira coluna.

    
por C.Mallia 23.01.2018 / 16:48

3 respostas

3

Adicionar a soma ao seu script não deve ser muito difícil, basta adicionar outro array para mantê-lo.

$ awk '{ if (a[$2]) a[$2] = a[$2] ", ";
         a[$2] = a[$2] $3;
         sum[$2] += $1 }
       END {for (x in a) printf "%3d %s %s\n", sum[x], x, a[x]}' inputfile
  2 account1 192.168.0.1, 192.168.0.2
 19 account2 192.168.0.1
101 account3 192.168.0.3, 192.168.0.5 

(Seu exemplo de saída tinha o endereço IP separado por vírgulas, então eu adicionei isso também. Embora pelo menos o código seja mais puro sem ele, na minha opinião.)

    
por 23.01.2018 / 17:11
2

Awk solução:

awk 'NR==1{ match($0, /^ +[^ ]+/); s=length(substr($0, RSTART, RLENGTH)) }
     { sum[$2]+=$1; ips[$2]=($2 in ips? ips[$2]", ":"")$3 }
     END{ 
         for (i in sum) 
             printf("%*s %s %s\n", s, sum[i], i, ips[i]) 
     }' file

A saída:

  2 account1 192.168.0.1, 192.168.0.2
 19 account2 192.168.0.1
101 account3 192.168.0.3, 192.168.0.5
    
por 23.01.2018 / 17:07
1

Provavelmente estou pensando demais nisso (há provavelmente um bom awk / sed para ser usado), mas essa é a melhor coisa que posso fazer:

#!/bin/bash
# set file as sys argument
file=$1

# pull unique account names into an array
account_names=($(awk '{print $2}' $file | sort | uniq))

# loop through and store column values
for account in ${account_names[@]}; do
    # get a sum of the first column
    col1=$(grep $account $file | awk '{SUM += $1} END {print SUM}')
    # get last column and convert to one line with comma separation
    IP_list=$(grep $account $file | awk '{print $NF}' | sort | uniq | tr '\n' ',' | sed s'/.$//')
    # print them together
    echo "$col1 $account $IP_list"
done

Então você pode executá-lo assim:

┌─[robotjohny@Fedora]─[~]─[04:08 pm]
└─[$]› ./test1.sh file1.txt 
2 account1 192.168.0.1,192.168.0.2
19 account2 192.168.0.1
101 account3 192.168.0.3,192.168.0.5
    
por 23.01.2018 / 17:09