You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell中带引号的"$@"展开为多参数的原因及解决方法

关于sh -c中$@参数传递的问题解答

先看两个实际执行的命令差异:

  • 执行这个命令会正常输出foo bar:
sh -c 'printf "$@"' -- "foo bar"
  • 但把参数拆成foo和bar分开传时,只会输出foo:
sh -c 'printf "$@"' -- foo bar

(sh和bash的表现一致)

问题1:为什么会出现这种情况?

你对引号的理解有个小偏差:引号是shell用来标记「单个参数边界」的工具,不是字符串本身的一部分。而$@的作用是把脚本的所有位置参数(也就是--后面的内容)逐个原样传递给后续命令。

具体来说:

  • 当你传-- "foo bar"时,sh -c的脚本拿到的位置参数只有1个:$1="foo bar",printf "$@"就等价于printf "foo bar",自然输出完整内容。
  • 当你传-- foo bar时,脚本拿到的位置参数是2个:$1="foo"、$2="bar",printf "$@"就等价于printf foo bar。而printf的规则是第一个参数作为格式字符串,后面的参数是填充格式的变量。这里foo里没有占位符(比如%s),所以printf只会输出格式字符串本身,第二个参数bar直接被忽略,最终只输出foo。

问题2:如何修改命令实现期望行为?

要让多个参数合并成单个字符串传给printf,有两种简单方法:

  1. 用$*代替$@:$*会把所有位置参数用系统默认的分隔符(默认是空格)拼接成一个字符串。命令如下:
sh -c 'printf "$*"' -- foo bar
  1. 显式指定printf的格式字符串,再用$*传递合并后的内容(更严谨,避免格式字符串意外):
sh -c 'printf "%s" "$*"' -- foo bar

内容的提问来源于stack exchange,提问作者ChrisB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:22:45