bash脚本中$ @和$ *的区别

下面有4个bash片段。 我用./script.sh abc调用它们

 for arg in $@; do echo "$arg" done ## output "a\nb\nc" for arg in "$@"; do echo "$arg" done ## output "a\nb\nc" -- I don't know why for arg in $*; do echo "$arg" done ## output "a\nb\nc" for arg in "$*"; do echo "$arg" done ## output "abc" 

我不知道$@$*之间的确切区别是什么,
我认为"$@""$*"应该是相同的,但它们不是。 为什么?

如果你有一个脚本foo.sh

 asterisk "$*" at-sign "$@" 

并用以下方式调用它:

 ./foo.sh "aa" "bb" "cc" 

它相当于:

 asterisk "aabbcc" at-sign "aa" "bb" "cc" 

没有引号,他们是一样的:

 asterisk $* at-sign $@ 

将相当于:

 asterisk "a" "a" "b" "b" "c" "c" at-sign "a" "a" "b" "b" "c" "c" 

$ *和$ @之间的区别是::

"$*" All the positional parameters (as a single word) *

"$@" All the positional parameters (as separate strings)

如果您使用./my_c $ @传递给bash脚本的三个命令行参数到一个C程序,

你会得到结果ARG[1] == "par1" ARG[2] == "par2" ARG[3] == "par3"

如果您使用./my_c $ *将三个命令行参数传递给C程序,

你得到结果ARG[1] == "par1 par2 par3"

这在shell脚本中很重要:例如脚本testargs.sh

 #! /bin/bash -p echo $# for i in $(seq 1 $#) do echo "$i: ${!i}" done for val in "$@"; do echo "in quote @, $val" done for val in "$*"; do echo "in quote *, $val" done for val in $@; do echo "not in quote @, $val" done for val in $*; do echo "not in quote *, $val" done 

如果此脚本以/tmp/testargs.sh abc 'd e' ,则结果为:

 4 1: a 2: b 3: c 4: de in quote @, a in quote @, b in quote @, c in quote @, de in quote *, abcde not in quote @, a not in quote @, b not in quote @, c not in quote @, d not in quote @, e not in quote *, a not in quote *, b not in quote *, c not in quote *, d not in quote *, e 

因此,如果要保存参数的数量,请始终使用“$ @”或使用for i in $(seq 1 $#)循环遍历每个参数。 没有引号,两者都是一样的。