考虑以下代码:
foo () {
echo $*
}
bar () {
echo $@
}
foo 1 2 3 4
bar 1 2 3 4
它输出:
1 2 3 4
1 2 3 4
我正在使用Ksh88,但是我也对其他常见的shell感兴趣。如果您碰巧知道特定外壳的任何特殊性,请提及它们。
我在Solaris的Ksh手册页中发现了以下问题:
当不加引号或用作参数赋值或用作文件名时,$ *和$ @的含义相同。但是,当用作命令参数时,$ *等效于``$ 1d $ 2d ...'',其中d是IFS变量的第一个字符,而$ @等效于$ 1 $ 2 ....
我尝试修改IFS
变量,但没有修改输出。也许我做错了什么?
当他们中没有报价,$*
并且$@
是相同的。您不应该使用其中任何一个,因为一旦您的参数包含空格或通配符,它们可能会意外中断。
"$*"
扩展为一个单词"$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
将其设置为非标准设置,则您随后运行的命令可能无法正常运行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句