Eu não posso dar a você algo tão bonito quanto a solução python do slhck, mas aqui está uma pura bash:
printf "\t" &&
for file in ex*; do \
printf "%-15s" "$file ";
done &&
echo "" &&
while read fruit; do \
printf "$fruit\t";
for file in ex*; do \
printf "%-15s" 'grep -wc $fruit $file';
done;
echo "";
done < superset.txt
Se você copiar / colar aquela coisa horrível em um terminal, supondo que sua lista de frutas esteja em um arquivo chamado superset.txt
com uma fruta por linha, você verá:
example1 example2 example3
apple 1 2 2
banana 1 1 2
mango 0 1 1
orange 1 1 2
pear 0 1 1
plum 0 0 1
EXPLICAÇÃO:
-
printf "\t"
: imprime uma TAB para que os nomes dos arquivos estejam alinhados ao final dos nomes das frutas.
-
for file in ex*; [...] done
: imprime os nomes dos arquivos (supondo que sejam os únicos arquivos cujo nome começa com ex
.
-
echo ""
: imprima uma nova linha
-
while read fruit; do [...]; done <list
: list
deve ser um arquivo de texto contendo o superconjunto mencionado, ou seja, todas as frutas, uma fruta por linha. Este arquivo é lido neste loop e cada fruta é salva como $fruit
.
-
printf "$fruit\t";
: imprime o nome da fruta e uma TAB.
-
for file in ex*; do [...]; done
: Aqui nós passamos por cada arquivo novamente e usamos grep -wc $fruit $file
para obter o número de vezes que a fruta que estamos processando atualmente foi encontrada naquele arquivo.
Você também pode usar column
mas eu nunca tentei:
The column utility formats its input into multiple columns.
Rows are filled before columns. Input is taken from file oper‐
ands, or, by default, from the standard input. Empty lines are
ignored unless the -e option is used.
E aqui está um Perl. Tecnicamente, este é um forro, ainda que LONGO:
perl -e 'foreach $file (@ARGV){open(F,"$file"); while(<F>){chomp; $fruits{$_}{$file}++}} print "\t";foreach(sort @ARGV){printf("%-15s",$_)}; print "\n"; foreach $fruit (sort keys(%fruits)){print "$fruit\t"; do {$fruits{$fruit}{$_}||=0; printf("%-15s",$fruits{$fruit}{$_})} for @ARGV; print "\n";}' ex*
Aqui está na forma de script comentada que pode ser inteligível:
#!/usr/bin/env perl
foreach $file (@ARGV){ ## cycle through the files
open(F,"$file");
while(<F>){
chomp;## remove newlines
## Count the fruit. This is a hash of hashes
## where the fruit is the first key and the file
## the second. For each fruit then, we will end up
## with something like this: $fruits{apple}{example1}=1
$fruits{$_}{$file}++;
}
}
print "\t"; ## pretty formatting
## Print each of the file names
foreach(sort @ARGV){
printf("%-15s",$_)
}
print "\n"; ## pretty formatting
## Now, cycle through each of the "fruit" we
## found when reading the files and print its
## count in each file.
foreach $fruit (sort keys(%fruits)){
print "$fruit\t"; ## print the fruit names
do {
$fruits{$fruit}{$_}||=0; ## Count should be 0 if none were found
printf("%-15s",$fruits{$fruit}{$_}) ## print the value for each fruit
} for @ARGV;
print "\n"; ## pretty formatting
}
Isso tem o benefício de lidar com "frutas" arbitrárias, não é necessário superconjunto. Além disso, essas duas soluções usam ferramentas * nix nativas e não exigem a instalação de pacotes adicionais. Dito isso, a solução python na resposta do slhck é mais concisa e dá uma saída mais bonita.