2016-08-02 108 views
2

我正在研究一些代碼優化,我會檢查我的函數的大小,而不是讀取巨大的反彙編文件。在Debug上編譯後,我使用nm命令讀取.o。我們拿到的這款:使用awk解析nm命令的輸出 - 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 

如今,走進一個bash腳本,我想解析只有第1列至極每一行代表在bash單個數組元素。

我的命令是:

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

併爲確保一切正常檢查我FUNCSIZE數組的大小。

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

我得到這個作爲輸出:

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

爲什麼大小是「1」,爲什麼我能打印每個元素就像是一個數組裏面。看起來輸出結果仍然有一個「空間」。是否有任何RegEx與awk,將避免將分隔符字段包含到數組中?

感謝您的幫助!

編輯答案

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

您正在讀取標量,而不是數組。也許你打算使用'read -a'。無論如何,創建一個bash數組可能是你接下來要做的任何事情的錯誤起點 - 如果你用一個簡明,可測試的例子告訴我們,我們可以幫助你。 –

+0

我們想製作一個工具來比較兩個不同的.o文件,並且比較任何函數是否已經及時更改。將大小解析爲變量將使腳本能夠檢查特定功能是否比以前更大。 –

+0

這將是一個awk腳本,所以從2個shell數組開始並不會有用。一個shell只是一個環境,通過它可以調用具有語言的工具來對這些調用進行排序,而標準的通用UNIX工具來處理文本是awk。 –

回答

1

這聽起來這樣從您的評論可能是你真正尋找:

$ 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 

上面使用GNU AWK爲strtonum(),並在這些2輸入文件運行:

$ 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 

只要與相應nm ...替換每個cat file

+1

Awesome Ed Morton! –

2

你寫它的方式之後,FUNCSIZE不是一個數組,而是一個普通的變量。

添加-a標誌read

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

注意,使用用戶定義的變量全部大寫的名稱是不建議,要avoid conflicts (and confusion) with environmental variables and special shell variables

(!感謝@mklement0的提示和鏈接)

+1

謝謝janos和Ed Morton。 -a標誌是我正在尋找的答案! –

+1

我建議要麼根本不顯示'FUNCSIZE =($(...))'選項,要麼將其稱爲反模式,因爲它會使命令替換的輸出受制於(通常不需要的)globbing(嘗試' a =($(echo'*'))'。也值得推薦不要使用全大寫變量名,並且常規地將'-r'選項添加到'read'。 – mklement0

+1

@ mklement0好點,謝謝,更新我的帖子。 – janos