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

Nay*_*iya 7 unix linux shell

谁能简单解释一下

  1. $*和$ @有什么区别?
  2. 为什么上面有相同内容的两个变量?

ɹɐq*_*ɹǝɟ 9

在这里看到这个:

$#    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" ...).
Run Code Online (Sandbox Code Playgroud)

举个例子

./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
Run Code Online (Sandbox Code Playgroud)


Jon*_*fer 7

除了技术文档中描述的差异之外,最好使用一些示例显示:

让我们假设我们有四个shell脚本test1.sh:

#!/bin/bash
rm $*
Run Code Online (Sandbox Code Playgroud)

test2.sh:

#!/bin/bash
rm "$*"
Run Code Online (Sandbox Code Playgroud)

test3.sh:

#!/bin/bash
rm $@
Run Code Online (Sandbox Code Playgroud)

test4.sh:

#!/bin/bash
rm "$@"
Run Code Online (Sandbox Code Playgroud)

(我在rm这里使用而不是echo,因为有echo,人们看不出差别)

我们使用以下命令行调用所有这些命令行,否则在一个空的目录中:

./testX.sh "Hello World" Foo Bar
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

这意味着,参数被视为一个完整的字符串,与空格连接,然后作为参数重新表示并传递给命令.将参数转发给另一个命令时,这通常没有用.

有了test2.sh,我们得到:

rm: cannot remove ‘Hello World Foo Bar’: No such file or directory
Run Code Online (Sandbox Code Playgroud)

所以我们有相同的test{1,3}.sh,但这一次,结果作为一个参数传递.

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
Run Code Online (Sandbox Code Playgroud)

这意味着参数的传递方式与它们传递给脚本的方式相同.将参数传递给其他命令时,这很有用.

区别是微妙的,但是在将参数传递给命令时会咬你,这些命令期望命令行中的某些点以及空间参与游戏时的信息.这实际上是大多数炮弹的许多陷阱之一的一个很好的例子.


Har*_*non 5

如果您不加引号$*或不加$@引号,则没有区别。但是,如果您将它们放在引号内(作为一般的良好做法,您应该这样做),那么$@会将您的参数作为单独的参数$*传递,而只会将所有参数作为单个参数传递。

使用这些脚本(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 "$@"
Run Code Online (Sandbox Code Playgroud)

现在这个例子应该让一切都清楚:

>> ./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
Run Code Online (Sandbox Code Playgroud)

显然,"$@"给出了我们通常想要的行为。


更详细的描述:

情况 1:$*和周围没有引号$@

两者都有相同的行为。

./bar.sh $*=>bar.sh获取arg1arg2arg3作为单独的参数

./bar.sh $@=>bar.sh获取arg1arg2arg3作为单独的参数

情况 2:您在$*和周围使用引号$@

./bar.sh "$*"=>作为单个参数bar.sh获取arg1 arg2 arg3

./bar.sh "$@"=> bar.shgets arg1arg2arg3作为单独的参数

更重要的是,$*还会忽略参数列表中的引号。例如,如果您提供了./foo.sh arg1 "arg2 arg3",即使这样:

./bar.sh "$*"=>bar.sh仍然会接收arg2arg3作为单独的参数!

./bar.sh "$@"=> 将arg2 arg3作为单个参数传递(这是您通常想要的)。

再次注意,只有将$*$@放在引号中时才会出现这种差异。否则他们有相同的行为。

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

  • 看起来很复杂。你能不能简单解释一下。 (2认同)