2016-08-02 23 views
2

Ich arbeite an einigen Code-Optimierung und ich würde die Größe meiner Funktionen statt zu lesen, um riesige Disassembly-Datei zu lesen. Nach dem Kompilieren auf Debug benutze ich den nm-Befehl, um das .o zu lesen. Wir haben dies:Parsing Ausgabe von nm Befehl mit Awk - Linux Bash

nm --size-sort $OBJFILEPATH.o 

000000000000000b r __PRETTY_FUNCTION__.6473 
0000000000000017 t extract_h 
0000000000000036 t L_mult 
000000000000003a t sature32 
0000000000000042 t L_mac 
0000000000000048 t L_add 
000000000000005c t Mac16x11 
0000000000000077 t L_shl 
0000000000000083 t L_shr 
00000000000000df T G729Convolve 
0000000000000114 T G729Residu 
00000000000001bc T G729Syn_filt_L_H 
00000000000001bc T G729Syn_filt_L_SUBFR 

nun in ein Bash-Skript, das ich nur die erste Spalte jeder Zeile ein einzelnes Array-Element in Bash darstellen wich analysieren möchten.

Mein Befehl lautet:

read FUNCSIZE <<< $(nm --size-sort $OBJFILEPATH.o | awk '{print $1}') 

Und stellen Sie sicher, dass alles in Ordnung ist, ich die Größe meiner FUNCSIZE Array überprüfen.

SIZE=${#FUNCSIZE[@]} 
echo size is $SIZE 
for s in $FUNCSIZE 
do 
    echo $s 
done 

Ich habe dies als Ausgabe:

size is 1 
000000000000000b 
0000000000000017 
0000000000000036 
000000000000003a 
0000000000000042 
0000000000000048 
000000000000005c 
0000000000000077 
0000000000000083 
00000000000000df 
0000000000000114 
00000000000001bc 
00000000000001bc 

Warum Größe ‚1‘ ist und warum ich in der Lage, jedes Element zu drucken, wie es in einer Reihe war. Es scheint, dass die Ausgabe immer noch ein 'Leerzeichen' am Ende der Zeile hat. Gibt es RegEx mit awk, das vermeidet, das Trennzeichenfeld in das Array aufzunehmen?

Vielen Dank für Ihre Hilfe !!

EDIT NACH ANTWORT

read -a FUNCSIZE <<< $(nm --size-sort $OBJFILEPATH.o | awk '{print $1}') 
SIZE=${#FUNCSIZE[*]} 
for((i=0; i<SIZE; i++)) 
do 
    echo ${FUNCSIZE[$i]} 
done 
+2

Sie lesen in einen Skalar, nicht in ein Array. Vielleicht wollten Sie 'read -a' verwenden. In jedem Fall ist das Erstellen eines Bash-Arrays wahrscheinlich der falsche Ausgangspunkt für das, was Sie als nächstes tun werden - wenn Sie uns das mit einem übersichtlichen, testbaren Beispiel erzählen, können wir Ihnen helfen. –

+0

Wir wollen ein Tool erstellen, das zwei verschiedene .o-Dateien vergleicht und vergleicht, wenn eine Funktion rechtzeitig geändert wurde. Durch das Parsen der Größe in eine Variable kann das Skript prüfen, ob eine bestimmte Funktion größer als vorher ist. –

+0

Das wäre ein awk-Skript, also wäre es nicht sinnvoll, mit 2 Shell-Arrays zu beginnen.Eine Shell ist nur eine Umgebung, von der aus Werkzeuge mit einer Sprache aufgerufen werden können, um diese Aufrufe zu sequenzieren, und das Standard-Universal-UNIX-Werkzeug zum Manipulieren von Text ist awk. –

Antwort

1

Es klingt aus Ihrem Kommentar, wie dies sein könnte, was Sie wirklich suchen:

$ cat tst.awk 
{ 
    size = strtonum("0x"$1) 
    sub(/^([^[:space:]]+[[:space:]]+){2}/,"") 
    name = $0 
} 
NR==FNR { oldSize[name] = size; next } 
{ 
    newSize[name] = size 
    if (name in oldSize) { 
     if (oldSize[name] < newSize[name]) { 
      bigger[name] 
     } 
     else if (oldSize[name] > newSize[name]) { 
      smaller[name] 
     } 
    } 
    else { 
     added[name] 
    } 
} 
END { 
    print "Got bigger:" 
    for (name in bigger) print "\t" name, oldSize[name], "->", newSize[name] 

    print "Got smaller:" 
    for (name in smaller) print "\t" name, oldSize[name], "->", newSize[name] 

    print "Added:" 
    for (name in added) print "\t" name 

    print "Deleted:" 
    for (name in oldSize) if (!(name in newSize)) print "\t" name 
} 

.

$ gawk -f tst.awk <(cat file1) <(cat file2) 
Got bigger: 
    Mac16x11 92 -> 93 
Got smaller: 
    L_mac 66 -> 65 
Added: 
    extract_h 
Deleted: 
    G729Residu 

Die oben verwendet GNU awk für strtonum() und wurde auf diesen zwei Eingabedateien ausführen:

$ cat file1 
000000000000000b r __PRETTY_FUNCTION__.6473 
0000000000000036 t L_mult 
000000000000003a t sature32 
0000000000000042 t L_mac 
0000000000000048 t L_add 
000000000000005c t Mac16x11 
0000000000000077 t L_shl 
0000000000000083 t L_shr 
00000000000000df T G729Convolve 
0000000000000114 T G729Residu 
00000000000001bc T G729Syn_filt_L_H 
00000000000001bc T G729Syn_filt_L_SUBFR 

$ cat file2 
000000000000000b r __PRETTY_FUNCTION__.6473 
0000000000000017 t extract_h 
0000000000000036 t L_mult 
000000000000003a t sature32 
0000000000000041 t L_mac 
0000000000000048 t L_add 
000000000000005d t Mac16x11 
0000000000000077 t L_shl 
0000000000000083 t L_shr 
00000000000000df T G729Convolve 
00000000000001bc T G729Syn_filt_L_H 
00000000000001bc T G729Syn_filt_L_SUBFR 

Ersetzen Sie einfach jede cat file mit der nm ... entspricht.

+1

Ehrfürchtige Ed Morton !! –

2

So wie du es geschrieben hat, ist FUNCSIZE kein Array, sondern eine reguläre Variable.

Fügen Sie die -a Flagge für read:

read -a FUNCSIZE <<< $(nm --size-sort $OBJFILEPATH.o | awk '{print $1}') 

Beachten Sie, dass alle Großbuchstaben Namen für benutzerdefinierte Variablen nicht zu empfehlen, zu avoid conflicts (and confusion) with environmental variables and special shell variables.

(! Dank @mklement0 für die Tipps und Links)

+1

Danke Janos und Ed Morton. Die Flagge war die Antwort, nach der ich gesucht habe !! –

+1

Ich schlage vor, entweder die 'FUNCSIZE = ($ (...)) 'Alternative überhaupt nicht zu zeigen oder sie als Anti-Muster aufzurufen, weil sie die Ausgabe der Befehlsersetzung einem (normalerweise unerwünschten) Globbing (try') unterwirft a = ($ (echo '*')) '. Es ist auch empfehlenswert zu empfehlen, keine Großbuchstaben-Variablennamen zu verwenden und routinemäßig die' -r'-Option zu 'read' hinzuzufügen. – mklement0

+1

@ mklement0 gute Punkte, danke, aktualisiert mein Beitrag – janos