Как убрать поля со всеми нулями - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть file, который выглядит так:

header,d0,d1,d2,d3, ...
s1,0,5,2,8, ...
s2,0,8,2,4, ...
s3,0,7,3,4, ...
s4,0,3,2,1, ...
...

Я хочу удалить любой столбец со всеми нулями, например, d0
Я могу вручную проверить столбцы со всеми нулями, найти d0 и выполнить

cut -d "," -f 1,3- file> file_revised  

Желаемый вывод

header,d1,d2,d3, ...
s1,5,2,8, ...
s2,8,2,4, ...
s3,7,3,4, ...
s4,3,2,1, ...
...

Но так как у меня так много столбцов, трудно проверить вручную.
Как я могу автоматически удалить столбцы со всеми нулями?
Спасибо.

Ответы [ 5 ]

0 голосов
/ 17 декабря 2018

Использование Perl

> cat sumin.txt
header,d0,d1,d2,d3
s1,0,5,2,8
s2,0,8,2,4
s3,0,7,3,4
s4,0,3,2,1
> cat rem_zero.sh
perl -F, -lane '
@FH=@F if $.==1;

if($.>1)
{
$F[$_] and $nz[$_]||=1 for 0..$#F;
push(@L,[@F]);
}

END {
@cols = grep $nz[$_], 0..$#nz;
print join(",",@FH[@cols]);
for my $line (@L) { print "@{$line}[@cols]" }
}

' $1
> rem_zero.sh sumin.txt
header,d1,d2,d3
s1 5 2 8
s2 8 2 4
s3 7 3 4
s4 3 2 1
>
0 голосов
/ 11 ноября 2018

Это поле, которое собирает поля для печати в переменную (p="$1,$3" ... и т. Д.) И использует system для вызова awk на print p:

$ awk '
BEGIN { FS=OFS="," }
NR==1 {
    for(i=1;i<=NF;i++)               # gather all field numbers to c[]
        c[i]
    next }
{
    for(i in c)                      # test all fields that still are all zeros
        if($i!=0)
            delete c[i] }
END {                                # after testing all the records
    for(i=1;i<=NF;i++)
        if(!(i in c))
            p=p (p==""?"":OFS) "$" i # make list of list of fields to print
    p="print " p                     # p="print $1,$3,$4,$5,$6"
    system("awk \047BEGIN{FS=OFS=\",\"}{" cmd "}\047 " FILENAME)
}' file

Выход:

header,d1,d2,d3, ...
s1,5,2,8, ...
s2,8,2,4, ...
s3,7,3,4, ...
s4,3,2,1, ...

Если все поля все нули, p="print" и весь файл печатается.

0 голосов
/ 11 ноября 2018

При условии, что первый столбец не содержит все нули, этот скрипт awk должен выполнить работу

awk -F',' '(NR==FNR && NR >1){for(i = 1; i <= NF; i++)
                              {a[i] = a[i]+$i}}
           (FNR!=NR){out=$1
                     for(i = 2; i<= NF; i++){
                      if(a[i]!=0){out=out","$i}
                     }
                    print out
                    }' file_name file_name

Обратите внимание, что скрипт получает имя входного файла file_name дважды!

Например, для ввода:

header,d0,d
s1,0,5,2,8,
s2,0,8,2,4,
s3,0,7,3,4,
s4,0,3,2,1,

скрипт выдает в качестве вывода

header,d
s1,5,2,8
s2,8,2,4
s3,7,3,4
s4,3,2,1
0 голосов
/ 11 ноября 2018

возможно, вы можете использовать команду sed, как показано ниже:

$ sed 's/\b0\,\b//g' test.txt
header,d0,d1,d2,d3
s1,5,2,8
s2,8,2,4
s3,7,3,4
s4,3,2,1
0 голосов
/ 11 ноября 2018
$ cat file
header,d0,d1,d2,d3
s1,0,5,2,8
s2,0,8,2,4
s3,0,7,3,4
s4,0,3,2,1
$
$ cat tst.awk
NR==1 {
    for (i=1; i<=NF; ++i)
        a[i]
    next
}
NR==FNR {
    for (i in a)
        if ($i != "0")
            delete a[i]
    next
}
{
    sep = ""
    out = ""
    for (i=1; i<=NF; ++i) {
        if (i in a)
            continue
        out = out sep $i
        sep = FS
    }
    print out
}
$
$ awk -F, -f tst.awk file file
header,d1,d2,d3
s1,5,2,8
s2,8,2,4
s3,7,3,4
s4,3,2,1
...