Я не могу дать вам что-то столь же красивое, как решение на python от slhck, но вот чисто 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
Если вы скопируете / вставите эту ужасную вещь в терминал, предполагая, что ваш список фруктов находится в файле с именем superset.txt
одному фрукту в строке, вы получите:
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
ОБЪЯСНЕНИЕ:
printf "\t"
: распечатать TAB, чтобы имена файлов были выровнены по концу названий фруктов.
for file in ex*; [...] done
: напечатать имена файлов (при условии, что они являются единственными файлами, имя которых начинается с ex
.
echo ""
: напечатать новую строку
while read fruit; do [...]; done <list
: list
должен быть текстовым файлом, содержащим упомянутое вами надмножество, т.е. все фрукты, по одному фрукту в строке. Этот файл читается в этом цикле, и каждый фрукт сохраняется как $fruit
.
printf "$fruit\t";
: напечатайте название плода и табуляцию.
for file in ex*; do [...]; done
: здесь мы снова просматриваем каждый файл и используем grep -wc $fruit $file
чтобы узнать, сколько раз в этом файле находился фрукт, который мы сейчас обрабатываем.
Вы также можете использовать column
но я никогда не пытался:
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.
А вот и Perl. Технически, это один лайнер, хотя и длинный:
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*
Вот он в форме комментария сценария, который на самом деле может быть понятным:
#!/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
}
Это дает преимущество совладания с произвольными "фруктами", а не суперсет. Кроме того, оба эти решения используют собственные инструменты * nix и не требуют установки дополнительных пакетов. Тем не менее, решение python в ответе slhck является более лаконичным и дает более приятный вывод.