quer a última linha quando o awk duplicado?

4

Eu tenho o arquivo:

key value

blah blah
blah blah
blahblah
man1 boy1
blah blah
man1 boy2
man1 boy1

Eu faço isso para remover linhas duplicadas:

awk '/man1/ { print $1,$2} ' file | awk '!x[$0]++'

e o comando pega a primeira linha e ignora outras linhas

man1 boy1 
man1 boy2

mas quero ignorar todas as linhas, exceto a última linha:

man1 boy2 
man1 boy1

como ramesh disse que eu quero algo como:

cat filename
blah blah
blah blah
blahblah
man1 boy1
blah blah
man1 boy2
man1 boy1
man1 boy2
man1 boy3
man1 boy4
man1 boy2

a saída desejada

man1 boy1
man1 boy3
man1 boy4
man1 boy2
    
por user79550 13.08.2014 / 22:16

6 respostas

6

você pode fazer isso usando este script de shell:

#!/bin/bash
awk '/man1/{pos[$0] = NR}
END {
  for(key in pos) reverse[pos[key]] = key
  for(nr=1;nr<=NR;nr++)
    if(nr in reverse) print reverse[nr]
}' yourfile

Saída:

[root@host ~]# sh shell.sh
man1 boy1
man1 boy3
man1 boy4
man1 boy2

Fonte

    
por 13.08.2014 / 23:57
7
tac filename |awk '/man1/ { print $1,$2} '| awk '!x[$0]++' | tac 

Teste

Eu queria testar com mais dados concretos. Então, meu teste é como abaixo.

cat filename
blah blah
blah blah
blahblah
man1 boy1
blah blah
man1 boy2
man1 boy1
man1 boy2
man1 boy3
man1 boy4
man1 boy2

Agora, eu corro o comando acima e obtenho a saída como

tac filename |awk '/man1/ { print $1,$2} '| awk '!x[$0]++' | tac
man1 boy1
man1 boy3
man1 boy4
man1 boy2

De acordo com a sugestão da Steeldriver, poderíamos modificar o awk para ser mais simples,

tac filename | awk '/^man1/ && !x[$2]++' | tac
    
por 13.08.2014 / 22:31
4

com zsh :

$ printf '%s\n' ${(Oau)${(MOa)${(f)"$(<file)"}:#man1*}}
man1 boy1
man1 boy3
man1 boy4
man1 boy2

Esses são sinalizadores de expansão de parâmetro :

  • f : dividido na nova linha
  • ${(M)array:#pattern} : expande para os elementos que correspondem ao padrão
  • Oa : inverter a ordem da matriz
  • u : exclusivo
por 14.08.2014 / 00:25
3

Uma solução específica do GNU awk:

gawk '
    $1 == "man1" {
        # remember the last line number
        x[$0] = NR
    } 
    END {
        # traverse the array by sorted numeric values
        PROCINFO["sorted_in"] = "@val_num_asc"
        for (line in x) 
            print line
    }
' file
man1 boy1
man1 boy3
man1 boy4
man1 boy2

Como uma linha concisa:

gawk '/man1/{x[$0]=NR}END{PROCINFO["sorted_in"]="@val_num_asc";for(l in x)print l}' file

Referências:
link link

    
por 13.08.2014 / 23:22
2

Uma solução de duas passagens. Na primeira passagem, capture os números de registro do último registro de cada chave em uma matriz. Na segunda passagem, imprima se o número do registro existir na matriz

awk 'NR == FNR{if ($0 ~ /man/)x[$0]=NR; next};
     FNR == 1{for (k in x) y[x[k]]=k};
     (FNR in y)' file file
man1 boy1
man1 boy3
man1 boy4
man1 boy2
    
por 13.08.2014 / 23:25
2

Lembre-se de mencionar o nome do arquivo duas vezes

awk '!/man1/{next}; NR == FNR {a[$0]++; next}; ++b[$0] == a[$0]' file file
    
por 14.08.2014 / 11:01