Ubuntu20.04下sudo执行awk命令未生效直接输出原文件内容
问题原因
该问题是多层Shell嵌套调用时的引号解析规则冲突、变量提前展开导致的参数传递错误:
- 直接执行awk命令时只有当前一层Shell解析,单引号可以正确包裹awk的字段分隔符参数、执行脚本,单引号内的
$2不会被Shell提前展开,所有参数都能完整传递给awk进程,因此执行结果符合预期。 - 执行
sudo -s bash -c "..."格式的命令时,参数会经过至少两轮解析:- 第一轮是当前普通用户的Shell解析双引号包裹的内容:双引号内的单引号会失去字符串定界的作用,仅作为普通字符传递,原本被单引号包裹的awk逻辑、分隔符参数会被拆分为零散的Shell参数,甚至
>会被识别为重定向语法;同时双引号内的$2会被当前Shell提前展开,若当前Shell没有传入第二个位置参数,$2会被替换为空值。 - 第二轮是sudo切换到root身份后,触发root用户的Shell再次解析拼接后的参数,进一步破坏原本要传给awk的参数结构。
最终awk收到的执行参数完全不符合预期,退化为打印文件整行内容。
- 第一轮是当前普通用户的Shell解析双引号包裹的内容:双引号内的单引号会失去字符串定界的作用,仅作为普通字符传递,原本被单引号包裹的awk逻辑、分隔符参数会被拆分为零散的Shell参数,甚至
解决方法
按优先级从高到低给出可行方案:
- 最优方案:去掉冗余的bash嵌套和cat管道,直接用sudo执行awk读取文件,完全规避多层转义问题
awk本身支持直接读取目标文件,不需要通过cat传递内容,也不需要嵌套bash -c调用,命令最简洁且无转义风险:sudo awk -F'Depends:' 'NF > 1 {print $2}' demo.txt - 方案2:保留原有命令结构的前提下,正确转义特殊字符
如果必须使用bash -c嵌套的写法,去掉多余的-s参数,同时对双引号内的$符号做转义,避免当前Shell提前展开变量:sudo bash -c "cat demo.txt | awk -F'Depends:' 'NF > 1 {print \$2}'" - 方案3:调整引号嵌套规则,用单引号包裹bash -c的执行参数
单引号内的所有特殊字符都会被当前Shell原样保留,不会触发提前解析,注意需要对内层的$符号做转义,避免被调用的bash进程提前展开:sudo bash -c 'cat demo.txt | awk -FDepends: "NF > 1 {print \$2}"'
内容的提问来源于stack exchange,提问作者vishal kulhari
相关产品推荐
相关产品推荐

