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

Posted

技术标签:

【中文标题】使用 awk 解析 nm 命令的输出 - Linux Bash【英文标题】:parsing output from nm command with awk - Linux Bash 【发布时间】:2016-08-02 16:11:25 【问题描述】:

我正在进行一些代码优化,我会检查我的函数的大小,而不是读取巨大的反汇编文件。在 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

为什么 size 是 '1' 以及为什么我能够像在数组中一样打印每个元素。似乎输出在行尾仍然有一个“空格”“”。是否有任何带有 awk 的 RegEx 可以避免将分隔符字段包含到数组中?

感谢您的帮助!!

回答后编辑

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

【问题讨论】:

您正在读入一个标量,而不是一个数组。也许您打算使用read -a。但无论如何,创建一个 bash 数组可能是您接下来要做的任何事情的错误起点 - 如果您通过一个简洁、可测试的示例告诉我们这一点,我们可以为您提供帮助。 我们想制作一个工具来比较两个不同的 .o 文件,并比较是否有任何功能被及时更改。将大小解析为变量,脚本将能够检查特定函数是否比以前更大。 那将是一个 awk 脚本,因此从 2 个 shell 数组开始不会有用。 shell 只是一个环境,可以使用一种语言来调用工具以对这些调用进行排序,而用于操作文本的标准通用 UNIX 工具是 awk。 这段代码实际上代表了一个shell脚本中的函数,但你是对的。我将使用 awk 代替。谢谢! 【参考方案1】:

按照你写的方式,FUNCSIZE 不是一个数组,而是一个常规变量。

read 添加-a 标志:

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

请注意,不建议对用户定义的变量使用全大写名称,avoid conflicts (and confusion) with environmental variables and special shell variables。

(感谢 @mklement0 的提示和链接!)

【讨论】:

谢谢 janos 和 Ed Morton。 -a 标志是我正在寻找的答案! 我建议要么根本不显示 FUNCSIZE=( $(...) ) 替代方案,要么将其称为反模式,因为它使命令替换的输出受到(通常不需要的)通配符(尝试 a=( $(echo '*') ) . 还值得推荐不要使用全大写的变量名,并定期将-r 选项添加到read【参考方案2】:

从您的评论看来,这可能是您真正想要的:

$ 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

上面的 strtonum() 使用 GNU awk 并在这两个输入文件上运行:

$ 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 ...

【讨论】:

真棒埃德莫顿!!

以上是关于使用 awk 解析 nm 命令的输出 - Linux Bash的主要内容,如果未能解决你的问题,请参考以下文章

使用awk命令循环查找并修改后输出。

Linux awk -F 命令如何指定输出双引号里的内容,求助

探索字符截取命令之---awk命令

awk从入门到入土(20)awk解析命令行参数

awk从入门到入土(20)awk解析命令行参数

3. linux常用命令及三剑客 grep sed awk 用法