awk comparison using arrays

4

Eu tenho o seguinte arquivo:

6180,6180,0,1,,1,0,1,1,0,0,0,0,0,0,0,0,4326,4326,,0.440000,
6553,6553,0,1,,1,0,1,1,0,0,0,0,1,0,1,0,4326,4326,,9.000000,
1297,1297,0,0,,0,0,1,0,0,0,0,0,1,0,1,0,1707,1707,,7.000000,
6598,6598,0,1,,1,0,1,1,0,0,0,1,0,0,0,0,1390,1390,,0.730000,
4673,4673,0,1,,1,0,1,1,0,0,0,0,0,0,0,0,1707,1707,,0.000000,

Eu preciso de um comando awk que imprima o valor máximo de $ 21 por $ 18.

a saída desejada será semelhante a:

6553,6553,0,1,,1,0,1,1,0,0,0,0,1,0,1,0,4326,4326,,9.000000,
1297,1297,0,0,,0,0,1,0,0,0,0,0,1,0,1,0,1707,1707,,7.000000,
6598,6598,0,1,,1,0,1,1,0,0,0,1,0,0,0,0,1390,1390,,0.730000,

Eu obtive este resultado, mas usando o comando sort, como abaixo:

sort -t, -k18,18n -k21,21nr | awk -F"," '!a[$18]++'

enquanto eu estou olhando para fazer isso com o comando awk único.

Por favor, conselhos,

    
por Eng7 29.07.2015 / 11:16

3 respostas

8

Eu não vejo por que você gostaria de fazer isso em um único comando awk , o que você tem parece perfeitamente bem. De qualquer forma, aqui está uma maneira:

$ awk -F, '(max[$18]<$21 || max[$18]==""){max[$18]=$21;line[$18]=$0}
            END{for(key in line){print line[key]}}' file
6598,6598,0,1,,1,0,1,1,0,0,0,1,0,0,0,0,1390,1390,,0.730000,
1297,1297,0,0,,0,0,1,0,0,0,0,0,1,0,1,0,1707,1707,,7.000000,
6553,6553,0,1,,1,0,1,1,0,0,0,0,1,0,1,0,4326,4326,,9.000000,

A ideia é muito simples. Temos duas matrizes, max tem $18 como uma chave e $21 como um valor. Para cada linha, se o valor salvo para $18 for menor que $21 ou se não houver nenhum valor armazenado para $18 , então armazenamos a linha atual ( $0 ) como o valor para $18 na matriz %código%. Finalmente, no bloco line , imprimimos o array END{} .

Observe que o script acima trata line como uma string. Portanto, $18 e 001 serão considerados sequências diferentes.

    
por 29.07.2015 / 11:35
4

Usar uniq em vez de awk pode ser mais rápido:

sort -t, -k18,18nr -k21,21nr | uniq -s39 -w4
    
por 29.07.2015 / 13:13
1

Você pode tentar seguir awk :

awk -F"," '{ if (max[$18] < $21) { max[$18] = $21; x[$18] = NR; } z[NR] = $0; } END { for (i in x) print z[x[i]]; }' file

Ele usa três matrizes max e x com as chaves da coluna $18 e z com números de linha de chaves. Em max , mantemos os valores máximos, em x , estamos mantendo o número da linha contendo o valor máximo e em z , todas as linhas do arquivo. No bloco END para cada chave na matriz x , imprimimos o valor de z[x[i]] .
Esta solução não é boa para arquivos grandes, pois lê arquivos inteiros na memória.

    
por 29.07.2015 / 11:34