简体   繁体   English

$ *和$ @之间有什么区别

[英]What is the difference between $* and $@

Who can simply explain 谁能简单解释一下

  1. what is the difference between $* and $@? $ *和$ @有什么区别?
  2. Why there are two variables for same content as above? 为什么上面有相同内容的两个变量?

Aside from the difference as described in the technical documents, it is best shown using some examples: 除了技术文档中描述的差异之外,最好使用一些示例显示:

Lets assume we have four shell scripts, test1.sh : 假设我们有四个shell脚本test1.sh

#!/bin/bash
rm $*

test2.sh : test2.sh

#!/bin/bash
rm "$*"

test3.sh : test3.sh

#!/bin/bash
rm $@

test4.sh : test4.sh

#!/bin/bash
rm "$@"

(I am using rm here instead of echo , because with echo , one can not see the difference) (我在这里使用rm而不是echo ,因为有了echo ,人们看不出差别)

We call all of them with the following commandline, in a directory which is otherwise empty: 我们使用以下命令行调用所有这些命令行,否则在一个空的目录中:

./testX.sh "Hello World" Foo Bar

For test1.sh and test3.sh , we receive the following output: 对于test1.shtest3.sh ,我们收到以下输出:

rm: cannot remove ‘Hello’: No such file or directory
rm: cannot remove ‘World’: No such file or directory
rm: cannot remove ‘Foo’: No such file or directory
rm: cannot remove ‘Bar’: No such file or directory

This means, the arguments are taken as a whole string, joined with spaces, and then reparsed as arguments and passed to the command. 这意味着,参数被视为一个完整的字符串,与空格连接,然后作为参数重新表示并传递给命令。 This is generally not helpful when forwarding arguments to another command. 将参数转发给另一个命令时,这通常没有用。

With test2.sh , we get: 使用test2.sh ,我们得到:

rm: cannot remove ‘Hello World Foo Bar’: No such file or directory

So we have the same as for test{1,3}.sh , but this time, the result is passed as one argument. 所以我们和test{1,3}.sh ,但这次,结果作为一个参数传递。

test4.sh has something new: test4.sh有一些新东西:

rm: cannot remove ‘Hello World’: No such file or directory
rm: cannot remove ‘Foo’: No such file or directory
rm: cannot remove ‘Bar’: No such file or directory

This implies that the arguments are passed in a manner equivalent to how they were passed to the the script. 这意味着参数的传递方式与它们传递给脚本的方式相同。 This is helpful when passing arguments to other commands. 将参数传递给其他命令时,这很有用。

The difference is subtle, but will bite you when passing arguments to commands which expect information at certain points in the command line and when spaces take part in the game. 区别是微妙的,但是在将参数传递给命令时会咬你,这些命令期望命令行中的某些点以及空间参与游戏时的信息。 This is in fact a good example of one of the many pitfalls of most shells. 这实际上是大多数炮弹的许多陷阱之一的一个很好的例子。

There is no difference if you do not put $* or $@ in quotes. 如果你没有在引号中加上$*$@ ,则没有区别。 But if you put them inside quotes (which you should, as a general good practice), then $@ will pass your parameters as separate parameters, whereas $* will just pass all params as a single parameter. 但是如果你把它们放在引号内(你应该这是一般的好习惯),那么$@会将你的参数作为单独的参数传递,而$*只会将所有参数作为单个参数传递。

Take these scripts ( foo.sh and bar.sh ) for testing: 使用这些脚本( foo.shbar.sh )进行测试:

>> cat bar.sh
echo "Arg 1: $1"
echo "Arg 2: $2"
echo "Arg 3: $3"
echo

>> cat foo.sh
echo '$* without quotes:'
./bar.sh $*

echo '$@ without quotes:'
./bar.sh $@

echo '$* with quotes:'
./bar.sh "$*"

echo '$@ with quotes:'
./bar.sh "$@"

Now this example should make everything clear: 现在这个例子应该让一切都清楚:

>> ./foo.sh arg1 "arg21 arg22" arg3
$* without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22

$@ without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22

$* with quotes:
Arg 1: arg1 arg21 arg22 arg3
Arg 2:
Arg 3:

$@ with quotes:
Arg 1: arg1
Arg 2: arg21 arg22
Arg 3: arg3

Clearly, "$@" gives the behaviour that we generally want. 显然, "$@"给出了我们通常想要的行为。


More detailed description: 更详细的描述:

Case 1: No quotes around $* and $@ : 案例1: $*$@附近没有报价:

Both have same behaviour. 两者都有相同的行为。

./bar.sh $* => bar.sh gets arg1 , arg2 and arg3 as separate arguments ./bar.sh $* => bar.sharg1arg2arg3作为单独的参数

./bar.sh $@ => bar.sh gets arg1 , arg2 and arg3 as separate arguments ./bar.sh $@ => bar.sharg1arg2arg3作为单独的参数

Case 2: You use quotes around $* and $@ : 案例2:您使用$*$@附近的报价:

./bar.sh "$*" => bar.sh gets arg1 arg2 arg3 as a single argument ./bar.sh "$*" => bar.sharg1 arg2 arg3作为单个参数获取

./bar.sh "$@" => bar.sh gets arg1 , arg2 and arg3 as a separate arguments ./bar.sh "$@" => bar.sharg1arg2arg3作为单独的参数获取

More importantly, $* also ignores quotes in your argument list. 更重要的是, $*也会忽略参数列表中的引号。 For example, if you had supplied ./foo.sh arg1 "arg2 arg3" , even then: 例如,如果你提供了./foo.sh arg1 "arg2 arg3" ,那么即便如此:

./bar.sh "$*" => bar.sh will still receive arg2 and arg3 as separate parameters! ./bar.sh "$*" => bar.sh仍将接收arg2arg3作为单独的参数!

./bar.sh "$@" => will pass arg2 arg3 as a single parameter (which is what you usually want). ./bar.sh "$@" =>将arg2 arg3作为单个参数传递(这是您通常想要的)。

Notice again that this difference occurs only if you put $* and $@ in quotes. 再次注意,只有在引号中放入$*$@时才会出现这种差异。 Otherwise they have the same behaviour. 否则他们有相同的行为。

Official documentation: http://www.gnu.org/software/bash/manual/bash.html#Special-Parameters 官方文档: http//www.gnu.org/software/bash/manual/bash.html#Special-Parameters

see this here : 看到这里

$#    Stores the number of command-line arguments that 
      were passed to the shell program.
$?    Stores the exit value of the last command that was 
      executed.
$0    Stores the first word of the entered command (the 
      name of the shell program).
$*    Stores all the arguments that were entered on the
      command line ($1 $2 ...).
"$@"  Stores all the arguments that were entered
      on the command line, individually quoted ("$1" "$2" ...).

take an example 举个例子

./command -yes -no /home/username
so now..
$# = 3
$* = -yes -no /home/username
$@ = ("-yes" "-no" "/home/username")
$0 = ./command
$1 = -yes
$2 = -no
$3 = /home/username

They are different when quoted: 引用时它们是不同的:

$ set "a b" c d 
$ echo $#
3
$ set "$*"
$ echo $#
1

$ set "a b" c d 
$ echo $#
3
$ set "$@"
$ echo $#
3

Here only the second form preserve the argument count. 这里只有第二种形式保留参数计数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM