2014-12-23 23 views
6

dieser Abtastwerteingang Gegeben:Berechnung Prozentsatz in beliebiger Anzahl von Spalten

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

Ich brauchte diese Ausgabe mit AWK zu produzieren:

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 

Dies ist, wie ich es gelöst:

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 
    } 
} 

Dies funktioniert gut in GNU AWK (awk in Linux, gawk in BSD), aber nicht in BSD AWK, wo ich diesen Fehler:

$ 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 

Es scheint, das Problem mit dem mehrdimensionalen Arrays ist. Ich möchte dieses Skript auch in BSD AWK arbeiten, , so dass es tragbarer ist.

Gibt es eine Möglichkeit, dies zu ändern, damit es in BSD AWK funktioniert?

+0

Einfache Antwort - versuchen nawk. Es sollte Teil der BSD-Installation sein. Einige Versionen von awk sind wirklich alt. –

Antwort

4

Verwenden Sie die pseudo-2-dimensionale Form. Statt

col[i][NR] 

Verwendung

col[i,NR] 

, dass ein 1-dimensionales Array ist, ist der Schlüssel der verketteten Zeichenfolge: i SUBSEP NR

3

@glenn ‚s Antwort hat mich auf dem richtigen Weg. Es dauerte jedoch ein wenig mehr Arbeit:

  • Verwendung von col[i, NR] gemacht Umgang mit den Spalten Titel mühsam. Es half sehr, die Pufferung der Spaltentitel zu entfernen und sie unmittelbar nach dem Lesen
  • length(col) + 1 war nicht mehr in der endgültigen Schleife Bedingung, wie mit col[i, j] machte die Schleifen unendlich. Als Abhilfe können, konnte ich length(col) + 1 mit einfach NF

Hier ist die endgültige Implementierung ersetzen, die jetzt sowohl GNU und BSD-Version von AWK funktioniert:

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 
    } 
} 
Verwandte Themen