当他们中没有报价,$*并且$@是相同的。您不应该使用任何一个,因为一旦您有包含空格或通配符的参数,它们可能会意外中断。
"$*"扩展为一个单词"$1c$2c..."。通常c是一个空格,但实际上是的第一个字符IFS,因此可以是您选择的任何内容。
我为此找到的唯一好的用途是:
用逗号连接参数(简单版本)
join1() {
typeset IFS=,
echo "$*"
}
join1 a b c # => a,b,c
使用指定的分隔符连接参数(更好的版本)
join2() {
typeset IFS=$1 # typeset makes a local variable in ksh (see footnote)
shift
echo "$*"
}
join2 + a b c # => a+b+c
"$@" 扩展为单独的单词: "$1" "$2" ...
这几乎总是您想要的。它将每个位置参数扩展为一个单独的单词,非常适合将命令行或函数参数传入,然后将其传递给另一个命令或函数。并且由于它使用双引号进行扩展,因此,如果"$1"包含空格或星号(*),则表示内容不会中断。
让我们写一个调用的脚本svim运行vim与sudo。我们将使用三个版本来说明差异。
svim1
#!/bin/sh
sudo vim $*
svim2
#!/bin/sh
sudo vim "$*"
svim3
#!/bin/sh
sudo vim "$@"
对于简单的情况,所有这些都很好,例如,一个不包含空格的文件名:
svim1 foo.txt # == sudo vim foo.txt
svim2 foo.txt # == sudo vim "foo.txt"
svim2 foo.txt # == sudo vim "foo.txt"
但是,只有$*和"$@"工作,如果正常,你有多个参数。
svim1 foo.txt bar.txt # == sudo vim foo.txt bar.txt
svim2 foo.txt bar.txt # == sudo vim "foo.txt bar.txt" # one file name!
svim3 foo.txt bar.txt # == sudo vim "foo.txt" "bar.txt"
而只有"$*"和"$@"正常工作,如果你有一个包含空格的参数。
svim1 "shopping list.txt" # == sudo vim shopping list.txt # two file names!
svim2 "shopping list.txt" # == sudo vim "shopping list.txt"
svim3 "shopping list.txt" # == sudo vim "shopping list.txt"
因此只有在"$@"所有时间都能正常工作。
typeset是如何在中创建局部变量ksh(bash并改为ash使用local)。这意味着IFS在函数返回时将恢复到其先前的值。这很重要,因为如果IFS将其设置为非标准设置,则随后运行的命令可能无法正常运行。