$ *和$ @有什么区别?

拉姆

考虑以下代码:

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是如何在中创建局部变量kshbash改为ash使用local)。这意味着IFS在函数返回时将恢复到其先前的值。这很重要,因为如果IFS将其设置为非标准设置,则您随后运行的命令可能无法正常运行

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章