2014-12-23 7 views
6

Given to wejście próbki:Obliczanie procenty w dowolnej ilości kolumn

ID  Sample1  Sample2  Sample3 
One  10   0   5 
Two  3   6   8 
Three 3   4   7 

mi potrzebny do wytworzenia tego wyjścia za pomocą AWK:

ID Sample1 Sample2 Sample3 
One 62.50 0.00 25.00 
Two 18.75 60.00 40.00 
Three 18.75 40.00 35.00 

ten sposób Rozwiązałem go:

function percent(value, total) { 
    return sprintf("%.2f", 100 * value/total) 
} 
{ 
    label[NR] = $1 
    for (i = 2; i <= NF; ++i) { 
     sum[i] += col[i][NR] = $i 
    } 
} 
END { 
    title = label[1] 
    for (i = 2; i <= length(col) + 1; ++i) { 
     title = title "\t" col[i][1] 
    } 
    print title 
    for (j = 2; j <= NR; ++j) { 
     line = label[j] 
     for (i = 2; i <= length(col) + 1; ++i) { 
      line = line "\t" percent(col[i][j], sum[i]) 
     } 
     print line 
    } 
} 

Działa to dobrze w GNU AWK (awk w systemie Linux, gawk w BSD), ale nie w BSD AWK, gdzie mogę dostać ten błąd:

$ awk -f script.awk sample.txt 
awk: syntax error at source line 7 source file script.awk 
context is 
      sum[i] += >>> col[i][ <<< 
awk: illegal statement at source line 7 source file script.awk 
awk: illegal statement at source line 7 source file script.awk 

Wydaje się, że problem jest z wielowymiarowych tablic. Chciałbym, aby ten skrypt działał również w BSD AWK, , dzięki czemu jest bardziej przenośny.

Czy istnieje sposób, aby to zmienić, aby działało w BSK AWK?

+0

Prosta odpowiedź - spróbuj nawk. Powinien być częścią instalacji BSD. Niektóre wersje awk są naprawdę stare. –

Odpowiedz

4

Spróbuj użyć pseudo-wymiarowego formularza. Zamiast

col[i][NR] 

użytku

col[i,NR] 

to jest 1-wymiarową tablicę, kluczem jest łączone ciąg: i SUBSEP NR

3

@glenn „s got me odpowiedź na właściwej ścieżce. Zajęło to trochę więcej pracy, ale:

  • Korzystanie col[i, NR] wykonane czynienia z tytułami kolumn kłopotliwe. Bardzo pomogło to w usunięciu buforowania tytułów kolumn i wydrukowaniu ich natychmiast po przeczytaniu, nie było już użyteczne w ostatecznym stanie pętli, ponieważ użycie col[i, j] spowodowało, że pętle były nieskończone. Jako obejście, mógłbym wymienić length(col) + 1 ze po prostu NF

Oto ostateczna realizacja, która teraz pracuje zarówno w wersji GNU oraz BSD AWK:

function percent(value, total) { 
    return sprintf("%.2f", 100 * value/total) 
} 
BEGIN { OFS = "\t" } 
NR == 1 { gsub(/ +/, OFS); print } 
NR != 1 { 
    label[NR] = $1 
    for (i = 2; i <= NF; ++i) { 
     sum[i] += col[i, NR] = $i 
    } 
} 
END { 
    for (j = 2; j <= NR; ++j) { 
     line = label[j] 
     for (i = 2; i <= NF; ++i) { 
      line = line OFS percent(col[i, j], sum[i]) 
     } 
     print line 
    } 
}