Seu programa awk
está correto se nós o modificarmos para incondicionalmente usar
print $0","( a[$3] ? a[$3] : 0 )
em vez de usar
print $0","a[$3]
quando a[$3]
é diferente de zero ou vazio.
Ou seja, use um zero se o campo a[$3]
for zero ou vazio, caso contrário, use a[$3]
.
Em outras palavras,
awk -F, -v OFS=',' 'FNR==NR { a[$1]=$2; next } FNR > 1 { print $0, (a[$3] ? a[$3] : 0) }' fileB fileA
Usamos FNR > 1
aqui para pular o cabeçalho.
Usando join
:
$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 fileA fileB
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
Se os arquivos não estão classificados na chave de junção, então (em um shell que suporta substituições de processos):
$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
4,1993,6050,912432,1.8 GHz
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
O join
executará uma operação INNER JOIN
nos dois arquivos. O -t ,
informa join
que as vírgulas são o delimitador de campo e escolhemos o terceiro campo como a chave de junção no primeiro arquivo com -1 3
(o primeiro campo no segundo arquivo é assumido como sendo a chave, a menos que -2 N
para o mesmo outro campo N
nesse arquivo).
O sinal -o
informa a join
quais campos gostaríamos de incluir na saída e de qual arquivo ( x.y
significa coluna y
do arquivo x
).
join
é uma operação muito rápida, mas requer que os arquivos de entrada sejam classificados na chave de junção (tivemos sorte com o primeiro exemplo acima). A saída final no segundo exemplo acima é não-classificada em relação ao campo primeiro , mas você pode consertar isso facilmente colocando-o em sort -k1,1n
.
Para o segundo cenário, com uma incompatibilidade,
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -a 1 -e 0 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
4,1993,6050,912432,1.8 GHz
A,B,C,D,0
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
Ao adicionar -a 1 -e 0
, pedimos que join
sempre exiba todos os campos do primeiro arquivo (-a 1
) e insira zeros para cada campo que estiver faltando no segundo arquivo.
Como você pode ver, agora obtemos o resultado correto, mas o cabeçalho do primeiro arquivo também está incluído (porque solicitamos). Se você quiser remover os cabeçalhos dos dados de ambos os arquivos (e classificar o resultado), então
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -e 0 -a1 <( tail -n +2 fileA | sort -t, -k3,3 ) <( tail -n +2 fileB | sort ) | sort -k1,1n
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
Este comando funcionaria realmente para ambos os cenários.