Eu usei awk
, que manipula vários arquivos de uma só vez:
sed 's/,R[1-9]\+\.csv:/,/g' <(awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" -F, '
{ seen[$1]=seen[$1]","FILENAME":"$2; }
END { print HEADER; for (x in seen) print x seen[x]}' R{1..3}.csv \
|awk -F, 'NR==1{split($0,arr,/,/);next} {SEP=""; fld=1;
for (x in arr){printf ($0 ~ arr[x])?SEP""$(fld++):",0";SEP=","};print ""}')
A saída:
A,1,0,1
B,20,0,4
C,30,1,0
D,0,13,0
E,0,15,2
F,0,19,0
G,0,0,6
H,0,0,8
Quebra de código:
awk -F, '{ seen[$1]=seen[$1]","FILENAME":"$2; }
END{ print HEADER; for (x in seen) print x seen[x] }' R{1..3}.csv
A parte principal do código que une toda a segunda coluna em todos os arquivos em uma impressão com o valor pertence a qual arquivo tem a mesma primeira coluna. O seen
aqui é um nome de matriz com a chave como primeira coluna e valor com ,FILENAME:$2
no modo de anexação.
Em seen[$1]=seen[$1]","FILENAME":"$2;
significa imprimir uma vírgula ,
seguido pelo arquivo de processamento atual FILENAME
com awk , dois pontos :
seguido pelo segundo valor da coluna $2
quando tiver o mesmo primeiro coluna seen[$1]=...
e anexar no mesmo índice de chaves =seen[$1]...
e salvar no mesmo valor da chave.
A instrução END
, awk executando este bloco no final quando todos os registros / linha foram lidos, e usamos um loop for para iterar o array visto e imprima a chave primeiro e o valor da chave na próxima.
resultará:
A,R1.csv:1,R3.csv:1
B,R1.csv:20,R3.csv:4
C,R1.csv:30,R2.csv:1
D,R2.csv:13
E,R2.csv:15,R3.csv:2
F,R2.csv:19
G,R3.csv:6
H,R3.csv:8
OK, agora sabemos que os valores de saída são de quais arquivos e quais arquivos não possuem esses dados. Para isso, preenchendo os dados dos arquivos não existentes com 0
, usei a substituição do comando shell para gerar uma linha de cabeçalho congaando todos os arquivos name e passou para awk como HEADER
-v aplicável:
awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" ...
mais tarde, usaremos essa linha HEADER
e preencheremos os dados dos arquivos perdidos com 0
. Agora nossa entrada é como este formato:
$ awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" -F, '
{ seen[$1]=seen[$1]","FILENAME":"$2; }
END { print HEADER; for (x in seen) print x seen[x]}' R{1..3}.csv
,R1.csv:,R2.csv:,R3.csv:
A,R1.csv:1,R3.csv:1
B,R1.csv:20,R3.csv:4
C,R1.csv:30,R2.csv:1
D,R2.csv:13
E,R2.csv:15,R3.csv:2
F,R2.csv:19
G,R3.csv:6
H,R3.csv:8
Em seguida, usei outro script awk abaixo para preencher os dados dos arquivos que não saem com 0
, que copiei da minha outra resposta à pergunta " Formatar e preencher dados perdidos com base na coluna ".
... |awk -F, 'NR==1{split($0,arr,/,/);next} {SEP=""; fld=1;
for (x in arr){printf ($0 ~ arr[x])?SEP""$(fld++):",0";SEP=","};print ""}'
No final, o sed 's/,R[1-9]\+\.csv:/,/g'
é usado para substituir o nome do arquivo existente no resultado por vírgula única ,
.