awk中非硬编码字符串问题:获取特定用户进程脚本失效
这个坑我踩过好多次!你遇到的核心问题是shell对单引号的处理规则:单引号包裹的内容会被shell原封不动地传递给awk,不会做任何变量替换。所以你写的$1 == "$(whoami)"里,$(whoami)根本没被解析成当前用户名,而是直接作为字符串"$(whoami)"传给awk,自然匹配不到正确的进程。
下面给你几种靠谱的解决方法,按推荐程度排序:
1. 用awk的-v选项传递变量(最推荐)
这是最清晰、最稳妥的方式,专门用来向awk脚本传递外部变量,完全避免引号嵌套的混乱:
# 先把用户名存到变量里,可读性更高 current_user=$(whoami) ps aux --sort -rss | awk -v user="$current_user" '$1 == user' # 也可以直接把命令嵌入,一步到位 ps aux --sort -rss | awk -v user="$(whoami)" '$1 == user'
-v user="$current_user"的作用是把shell变量current_user的值传给awk的内部变量user,之后在awk脚本里直接用user就行,完全不会和shell的变量解析冲突。
2. 改用双引号包裹awk脚本(需转义特殊字符)
如果一定要用引号包裹整个awk脚本,可以把单引号换成双引号,但要注意转义awk里的$(因为shell会把$1当成自己的位置参数):
ps aux --sort -rss | awk "\$1 == \"$(whoami)\""
这里的\$1告诉shell不要解析这个$,把它原封不动传给awk;\"则是转义双引号,避免和外层的双引号冲突。这种方法可行,但引号多了容易晕,不如第一种直观。
3. 单引号拼接变量(适合简单场景)
你可以把awk脚本拆成几部分,在单引号外面拼接变量:
ps aux --sort -rss | awk '$1 == "'$(whoami)'"'
shell会先解析$(whoami)得到用户名,然后把三部分内容拼接起来传给awk:$1 == "你的用户名"。不过如果用户名里包含特殊字符(比如空格、引号),这种方法会出问题,所以只推荐在用户名简单的时候用。
额外小技巧:直接用ps的用户过滤选项
其实根本不用awk,ps本身就支持按用户过滤进程,写法更简单:
ps -u $(whoami) --sort -rss
-u选项后面跟用户名,直接只输出该用户的进程,再加上--sort -rss按内存占用倒序排列,完美实现你的需求。
内容的提问来源于stack exchange,提问作者Maligetzus

