AWK中如何在system()函数中传入变量值以通过PID获取进程名?
解决AWK中system()调用变量的问题
你遇到的核心问题有两个:AWK不支持用+做字符串拼接,而且system()返回的是命令的退出状态码,不是命令的输出内容——这俩坑刚好你都踩了😅
先修正字符串拼接错误
AWK里的字符串拼接逻辑很简单:只要把变量和字符串直接放在一起(中间可以加空格分隔,不影响),不需要用+号。你原来的"ps -p "+names[n-1]+" -o comm="是C/Java的写法,在AWK里完全不生效,改成下面的形式就行:
"ps -p " names[n-1] " -o comm="
再解决获取命令输出的问题
system()函数只会返回命令的执行结果(0表示成功,非0表示失败),如果你想拿到ps命令输出的进程名,得用管道+getline的方式捕获输出,而不是直接打印system()的返回值。
修正后的完整代码
awk '{ n=split($0,names,"/"); pid=names[n-1]; # 单独存PID,代码更清晰 cmd="ps -p " pid " -o comm="; # 用getline捕获命令输出 if ((cmd | getline proc_name) > 0) { print proc_name; # 打印真正的进程名 } else { print "无法获取PID " pid " 的进程名"; } close(cmd); # 一定要关闭管道,避免资源泄漏 }' <<< "/usr/lib/firefox/firefox/1319/1000"
额外细节说明
- 关于
split的索引:你的输入字符串开头是/,所以split($0,names,"/")后,数组names的第一个元素是空值,后面的元素依次是usr、lib...1319、1000,所以names[n-1]确实能拿到目标PID1319,这部分逻辑是对的。 getline的返回值:它会返回读取到的行数,>0表示成功读取到输出,0表示命令执行成功但无输出,-1表示命令执行失败。- 管道关闭:每次用
cmd | getline后必须调用close(cmd),否则多次执行会占用文件描述符,导致程序报错。
可选简化写法(GNU AWK适用)
如果你的环境用的是GNU AWK(绝大多数Linux系统默认都是),也可以用vsprintf构造命令字符串,写法更接近C语言的格式化输出:
cmd = vsprintf("ps -p %s -o comm=", names[n-1])
测试的时候可以先单独执行ps -p 1319 -o comm=,确认这个PID确实存在且能返回进程名,再放到AWK里运行。
内容的提问来源于stack exchange,提问作者lancaster




