Для более сложных деревьев перенаправления файловых дескрипторов есть pipexec, который попал в репозиторий Debian.
Воистину, это ограничение синтаксиса в BASH и в Bourne-подобных оболочках в целом.
Поскольку эти значения всегда являются целыми числами, вы можете сделать что-то вроде:
cut $(awk 'NR>1{for(i=2;i<=NF;i++) s[i]+=$i}END{printf("%s", "-f 1");
for (i=2;i<=NF;i++) {if (s[i]) printf(",%s", i)}}' infile) infile
это читает файл дважды: awk
получает номера столбцов, сумма которых не равна нулю; затем они используются с вырезом
для печати только требуемых столбцов.
, чтобы удалить столбец
c.awk:
{ for(i=1;i<=NF;i++) { line[NR][i]=$i ; col[i]+=$i ;} }
END {
for ( l=1 ; l<=NR ; l++ )
{
printf line[l][1] "\t" ;
for (c=2;c<=NF;c++) if (col[c]) printf line[l][c] "\t" ;
printf "\n" ;
}
}
где
{for (i = 1; i <= NF; i ++) {line [NR] [i] = $ i; col [i] + = $ i;}}
сохраняет всю строку (включая имена столбцов). Предложение END
печатает весь столбец, если count! = 0. тест:
awk -f c.awk a
a b c
e 1 2
f 3 4
g 5 6
для строкового решения ...
попробуйте
awk 'NR==1 {print } NR>1 { s=0 ; for(i=1;i<=NF;i++) s+=$i ; if (s) print ;}'
где
NR == 1 {print}
print header NR> 1 {s = 0; для (i = 1; i <= NF; i ++) s + = $ i; if (s) print;}
проверка на 0 и печать, если нет i = 2
, если первый столбец является именем строки. обратите внимание, что это будет выводить строки, а не удалять из исходного файла.
Это может быть проще с perl
, если вы хотите сохранить интервалы:
perl -lne '
$i = 0;
for (/\S+\s*/g) {
$cell[$.][$i] = $_;
$sum[$i++] += $_
}
END{
@keep=(0, grep {$sum[$_]} (1..$#sum));
print((@{$cell[$_]})[@keep]) for (1..$.)
}'
Это загружает весь файл в память. Чтобы избежать этого, вам понадобится два прохода в файле.
Это можно сделать с помощью комбинации awk
и sed
:
awk '
NR>1{for (i=2; i<=NF; i++) sum[i]+=$i; if (NF>n) n = NF}
END {
for (;n>1;n--)
if (!sum[n])
print "s/[^[:blank:]]\\{1,\\}[[:blank:]]*//" n
}' < file | sed -f - file
awk
генерирует сценарий sed
для удаления столбцов, сумма которых равна 0. Команды s/[^[:blank:]]\{1,\}[[:blank:]]*//3
sed
удалят столбцы с сохранением интервалов между остальными столбцами, но это будет довольно дорого, вы можете захотеть сделать это удаление в perl
, если производительность является проблемой.
Для строк все гораздо проще:
perl -MList::Util=sum -lane 'print if $. == 1 or sum @F'