使用awk解析nm命令的输出 - Linux Bash

3

我正在进行一些代码优化工作,想要检查我的函数的大小,而不是读取巨大的反汇编文件。在 Debug 编译后,我使用 nm 命令来读取 .o 文件,我们得到了以下结果:

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脚本中解析每一行的第一列,而每一行代表了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数组可能不是你接下来要做的正确起点。如果你能用简明、可测试的例子告诉我们你要做什么,我们可以帮助你。 - Ed Morton
我们想制作一个工具,可以比较两个不同的.o文件,并比较是否有任何函数在时间上发生了变化。将大小解析为变量后,脚本就能够检查特定函数是否比以前更大。 - SAN ALexis
这将是一个awk脚本,因此从2个shell数组开始并不有用。Shell只是一个环境,用于使用语言调用工具并对这些调用进行序列化,而标准的通用UNIX文本处理工具是awk。 - Ed Morton
1
这段代码实际上代表了一个 shell 脚本中的函数,但你是对的。我会使用 awk 代替。谢谢! - SAN ALexis
2个回答

2

1
谢谢Janos和Ed Morton。-a标志就是我正在寻找的答案!! - SAN ALexis
1
我建议要么根本不显示FUNCSIZE =($(...))替代方案,要么将其标注为反模式,因为它使命令替换的输出受到(通常不需要的)全局影响(尝试a =($(echo'*')))。还值得推荐不使用全大写变量名称,并经常添加-r选项到read中。 - mklement0

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()函数,并在这两个输入文件上运行:
$ 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

只需将每个 cat file 替换为相应的 nm ...

1
厉害的 Ed Morton!! - SAN ALexis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接