在许多SO问题和bash教程中,我看到我可以通过两种方式访问bash脚本中的命令行参数:
$ ~ >cat testargs.sh
#!/bin/bash
echo "you passed me" $*
echo "you passed me" $@
结果是:
$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2
$*和$@有什么区别?
什么时候应该使用前者,什么时候应该使用后者?
$*
展开到位置参数,从1开始。当
展开发生在双引号内,它展开为单个单词
的第一个字符分隔每个参数的值
IFS特殊变量。也就是说,“$*”相当于“$1c$2c…”,
其中c是IFS变量值的第一个字符。如果
不设置IFS,参数间以空格分隔。如果IFS为空,
参数的连接没有中间分隔符。
$@
Expands to the positional parameters, starting from one. When the
expansion occurs within double quotes, each parameter expands to a
separate word. That is, "$@" is equivalent to "$1" "$2" ... If the
double-quoted expansion occurs within a word, the expansion of the
first parameter is joined with the beginning part of the original
word, and the expansion of the last parameter is joined with the last
part of the original word. When there are no positional parameters,
"$@" and $@ expand to nothing (i.e., they are removed).
来源:Bash man
当特殊参数被引用时,会出现差异。让我来说明一下它们的区别:
$ set -- "arg 1" "arg 2" "arg 3"
$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3
$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3
$ for word in "$*"; do echo "$word"; done
arg 1 arg 2 arg 3
$ for word in "$@"; do echo "$word"; done
arg 1
arg 2
arg 3
关于引用重要性的另一个例子:注意在“arg”和数字之间有2个空格,但如果我没有引用$word:
$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3
在bash中,“$@”是迭代的“默认”列表:
$ for word; do echo "$word"; done
arg 1
arg 2
arg 3
$*
展开到位置参数,从1开始。当
展开发生在双引号内,它展开为单个单词
的第一个字符分隔每个参数的值
IFS特殊变量。也就是说,“$*”相当于“$1c$2c…”,
其中c是IFS变量值的第一个字符。如果
不设置IFS,参数间以空格分隔。如果IFS为空,
参数的连接没有中间分隔符。
$@
Expands to the positional parameters, starting from one. When the
expansion occurs within double quotes, each parameter expands to a
separate word. That is, "$@" is equivalent to "$1" "$2" ... If the
double-quoted expansion occurs within a word, the expansion of the
first parameter is joined with the beginning part of the original
word, and the expansion of the last parameter is joined with the last
part of the original word. When there are no positional parameters,
"$@" and $@ expand to nothing (i.e., they are removed).
来源:Bash man
这个例子让我们在使用“at”和“asterix”时突出它们之间的区别。
我声明了两个数组水果和蔬菜
fruits=(apple pear plumm peach melon)
vegetables=(carrot tomato cucumber potatoe onion)
printf "Fruits:\t%s\n" "${fruits[*]}"
printf "Fruits:\t%s\n" "${fruits[@]}"
echo + --------------------------------------------- +
printf "Vegetables:\t%s\n" "${vegetables[*]}"
printf "Vegetables:\t%s\n" "${vegetables[@]}"
请看上面代码的结果:
Fruits: apple pear plumm peach melon
Fruits: apple
Fruits: pear
Fruits: plumm
Fruits: peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion