2012-03-30 8 views
0

Ich habe einige awk-Code, der wirklich langsam läuft. Das Format meiner Datei ist tabulatorgetrennte 5 Spalten ASCII. Ich Betrieb auf Spalte 5 eine Anzahl von entsprechenden Zeichen zu erhalten, den Wert in Spalte 4Beschleunigen Sie meine awk Befehl? Antwort muss awk sein :)

Beispiel Eingangsleitung zu verändern:

10 5134832 28 N * Aaaaa AAAAaAAAaAAAAaAAAA ^]^a] a^Fa ^] a

Wenn ich "^" in $ 5 finde, möchte ich es nicht zählen, oder das folgende Zeichen. Dann möchte ich herausfinden, wie viele Zeichen ">" oder "<" oder "*" sind und sie aus der Zählung entfernen. Ich schätze mit einem gsub, und 3 Splits ist weniger als ideal, zumal Spalte 5 gelegentlich eine sehr sehr lange Zeichenfolge sein kann.

awk '{l=$4; if($5~/>/ || $5~/</ || $5~/*/) {gsub(/\^./,"");l-=split($5,a,"<")-1;l-=split($5,a,">")-1;l-=split($5,a,"*")-1} 

Wenn der Code oben erfolgreich auf der Linie verläuft, wird l sein 27.

ich die umliegenden Teile des Befehls am Weglassen von Seiten, um zu versuchen und konzentriere ich mir eine Frage zu haben.

Also, was ist der beste Schritt, um das schneller zu machen?

+0

Rewrite es in Assembler :) –

Antwort

1

Nun, wie ich sehe, wird Ihre gsub Muster nicht funktionieren, wie die / wurde nicht geschlossen. Wie auch immer, wenn ich es richtig und Sie wollen die Zeichenanzahl von $5 ohne einige Zeichen, würde ich mit gehen:

count=length(gensub("[><A-Z^]","","g",$5)) 

Sie sollten Ihre überspringbarer Zeichen zwischen [ Liste und ], und beginnen Sie nicht mit ^!

+0

Dank Zsolt. Der hinzugefügte Trick ist, dass ich einige Zeichen weglassen möchte und dabei alle Zeichenpaare von "^ [A-Z]" weglassen möchte. – lonestar21

+1

Was meinst du mit Zeichenpaaren? –

+0

Ich habe die Frage bearbeitet, um zu zeigen, was ich unter Zeichenpaaren verstehe. Oben möchte ich "^]" und "^ F" von meinem Zählen weglassen. – lonestar21

1

Hier ist eine Vermutung:

awk ' 
    BEGIN {FS = OFS = "\t"} 
    { 
     str = $5 
     gsub(/\^.|[><*]/, "", str) 
     l = length(str) 
    } 
' 
+0

Also im Allgemeinen sollte Gsub auf mehreren Charaters schneller als mehrere Splits sein? – lonestar21

+0

@ lonestar21, weiß es nicht, versuchen Sie es und sehen. Bei mehreren Splits muss awk mehrere Arrays im Speicher erstellen. –

+0

@ lonestar21, aktualisiert, um Ihre Frage zu aktualisieren –

1

Haben Sie awk verwenden müssen, oder wird stattdessen das funktionieren?

cut -f 5 < $file | grep -v '^[A-Z]' | tr -d '<>*\n' | wc -c 

Übersetzung:

  • Extrahieren Sie das fünfte Feld aus der Tab-separierte $file.
  • Entfernen Sie alle Felder, die mit einem Großbuchstaben beginnen.
  • Entfernen Sie die Zeichen <, >, * und Zeilenumbrüche.
  • Die verbleibenden Zeichen zählen.
+0

Ich muss irgendwie awk verwenden, da dies Teil eines größeren awk Befehls ist. – lonestar21

+1

Ok. Aber keine faire Änderung der Spezifikationen in der Frage _after_ Antworten werden veröffentlicht! ;-) –

0

Dies könnte für Sie arbeiten:

echo "10 5134832 N 28 Aaaaa*AAAAaAAAaAAAAaAAAA^]a^]a^Fa^]a" | 
awk '/[><*^]/{t=$5;gsub(/[><*]|[\^]./,"",t);$4=length(t)}1' 
10 5134832 N 27 Aaaaa*AAAAaAAAaAAAAaAAAA^]a^]a^Fa^]a 

, wenn Sie die geänderte fünfte Feld angezeigt werden soll:

awk '/[><*^]/{gsub(/[><*]|[\^]./,"",$5);$4=length($5)}1'