当他们中没有报价,$*
并且$@
是相同的。您不应该使用任何一个,因为一旦您有包含空格或通配符的参数,它们可能会意外中断。
"$*"
扩展为一个单词"$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
将其设置为非标准设置,则随后运行的命令可能无法正常运行。