在Bash脚本中,$@和$*有什么区别?

5
我是新手学习bash,对于使用$@S*之间的实际区别有疑问。
在这里我阅读了Bash特殊参数
我明白两个参数都扩展到位置参数上,但在双引号内使用时会出现区别。顺便说一下,"$@" = "$1" "$2"..."$n"可能与"S*" = "$1$2...$n"不同。
我试图用一个简单的脚本来理解它:
if [ $# -gt 0 ]; then
       echo "Your command line contains $# arguments" 
else
       echo "Your command line contains no arguments"
       exit  fi

echo "Params are: "
echo $@  
echo $* 
echo "$@"    
echo "$*"

如果我像这样在终端中执行我的脚本~./my_script par1 par2 par3

结果总是一样的:

Params are:
par1 par2 par3
par1 par2 par3
par1 par2 par3
par1 par2 par3

也许我不太理解特殊变量的实际用途,以及我的例子是否正确。我希望通过一个好的例子来搞清楚这一点。

请参见https://dev59.com/VnA75IYBdhLWcg3w9-Ox。 - devnull
啊,好的。抱歉重复问题,但我想在我的例子中也理解一下。 - Kyrol
1
这些相关问题都有相当详细的解释。请参见https://dev59.com/VnA75IYBdhLWcg3w9-Ox#3008734和https://dev59.com/unE85IYBdhLWcg3wejVO#2761739和https://dev59.com/unE85IYBdhLWcg3wejVO#14247889和https://dev59.com/VnA75IYBdhLWcg3w9-Ox#14247867。 - devnull
大量的解释!谢谢! - Kyrol
2个回答

4
他们在使用echo时可能看起来相同,但这是因为它们被echo同等对待而不是等价的。
如果将bash脚本传递的三个命令行参数使用./my_c $@传递给C程序,则会得到结果ARGV[1] == "par1"ARGV[2] == "par2"ARGV[3] == "par3"
如果将bash脚本传递的三个命令行参数使用./my_c $*传递给C程序,则会得到结果ARGV[1] == "par1 par2 par3"
ARGV是C语言中提供的参数数组,第一个元素始终是程序调用时使用的命令名称)
这样做是为了在脚本后面更灵活地处理给定的参数。

感谢您的 C 语言解释。 - Kyrol

3

http://tldp.org/LDP/abs/html/refcards.html

"$*" 所有位置参数(作为一个单词)*

"$@" 所有位置参数(作为单独的字符串)

这段代码展示了它:给定一个由空格分隔的项目字符串,$@将每个单词视为新项目,而$*将它们全部视为同一参数。

echo "Params for: \$@"
for item in "${@}"
do
        echo $item --
done

echo "Params for : \$*"
for item in "${*}"
do
        echo $item --
done

测试:

$ ./a par1 par2 par3
Your command line contains 3 arguments
Params for: $@
par1 --
par2 --
par3 --
Params for : $*
par1 par2 par3 --

因此,在我的示例中使用echo并不能说明区别。 - Kyrol
1
没错,@Kyrol。当你把变量放进循环中展示它正在获取哪些“片段”时,你可以获取到更准确的信息。 - fedorqui
另一个疑问:在这种情况下,您使用的for循环中的"${@}""$@"之间有什么区别吗?我认为它们是相同的。 - Kyrol
是的,@Kyrol,${var_name}$var_name完全相同。我加上这个是因为我在 https://dev59.com/hG3Xa4cB1Zd3GeqPi9C-#14588210 中检查我的答案,那里空格确实很重要,并且用"${x[@]}"考虑了空格。 - fedorqui
我看到了你回答的问题。再次感谢您的解释!;) - Kyrol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接