如何在Bash函数中保留引号?带引号参数调用异常排查
这个问题我太熟了——Bash函数里参数传递的引号处理坑很多,咱们一步步来理清楚:
首先说为啥第二个命令会失败:当你敲foo cmake -G "Unix Makefiles" ...的时候,Bash会先把命令行解析成几个独立参数:cmake、-G、Unix Makefiles(因为引号的存在,这是一个整体参数)、-DARCHITECTURE_TYPE=armv7_32。但你的原函数里执行$@时没加双引号,这会让Bash对每个参数再做一次分词——原本是一个整体的Unix Makefiles会被拆成Unix和Makefiles两个参数传给cmake。这下cmake就懵了,它以为你要找名叫Unix的生成器,自然就报错了。
1. 核心修复:保留参数完整性
只要修改函数,在执行命令时用双引号把$@包起来,就能让每个参数原封不动地传递:
foo() { echo "run '$*'" # $*会把所有参数合并成一个字符串,和你原来的输出格式一致 "$@" # 双引号包裹$@,严格保留每个参数的独立性 } export -f foo
现在再执行foo cmake -G "Unix Makefiles" -DARCHITECTURE_TYPE=armv7_32,cmake会收到完整的-G "Unix Makefiles"参数,生成器就能正确识别了。
2. 可选优化:让输出也保留原始引号
如果你希望echo的内容里也显示原始的引号(比如输出run 'cmake -G "Unix Makefiles" -DARCHITECTURE_TYPE=armv7_32'),可以用printf来精准打印:
foo() { printf "run '" printf "%q " "$@" # %q会自动给带空格的参数加上引号,还原原始命令的样子 printf "'\n" "$@" } export -f foo
这个版本的输出会更贴近你输入的原始命令,同时执行逻辑依然正确。
最后补一句:为啥之前foo cmake --build .能正常工作?因为--build和.都是没有空格的参数,就算没加双引号,Bash也不会拆分它们,所以cmake能收到正确的参数,自然编译成功。
内容的提问来源于stack exchange,提问作者Werner

