Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么$@的工作方式与bash中的大多数其他变量不同?_Bash_Quotes - Fatal编程技术网

为什么$@的工作方式与bash中的大多数其他变量不同?

为什么$@的工作方式与bash中的大多数其他变量不同?,bash,quotes,Bash,Quotes,$@变量似乎在其参数周围保留引号,例如: $ function foo { for i in "$@"; do echo $i; done } $ foo herp "hello world" derp herp hello world derp 我还知道bash数组的工作方式是相同的: $ a=(herp "hello world" derp) $ for i in "${a[@]}"; do echo $i; done herp hello world derp 像这样的变量到底是怎么回

$@变量似乎在其参数周围保留引号,例如:

$ function foo { for i in "$@"; do echo $i; done }
$ foo herp "hello world" derp
herp
hello world
derp
我还知道bash数组的工作方式是相同的:

$ a=(herp "hello world" derp)
$ for i in "${a[@]}"; do echo $i; done
herp
hello world
derp

像这样的变量到底是怎么回事?特别是当我在引文中加上“duck${a[@]}goose”这样的词时。如果它没有空格分隔,那它是什么?

通常,Bash中的双引号表示“将引号之间的所有内容都放在一个单词中,即使其中包含分隔符。”但是正如您所注意到的,
$@
在双引号内时的行为不同。这实际上是一种可以追溯到Bash的前身Bourne shell的解析攻击,这种特殊行为只适用于这个特定变量

如果没有这种技巧(我使用这个术语是因为从语言的角度来看它似乎不一致,尽管它非常有用),shell脚本将很难将其参数数组传递给需要相同参数的其他命令。其中一些参数中可能包含空格,但是如果shell不将它们作为一个大词集中在一起,或者重新划分列表并拆分包含空格的参数,它如何将它们传递给另一个命令

您可以传递一个参数数组,Bourne shell实际上只有一个数组,由
$*
$@
表示,其元素数为
$#
,其元素为
$1
$2
,等等,即所谓的位置参数

示例。假设当前目录中有三个文件,分别名为
aaa
bbb
、和
cc c
(第三个文件的名称中有空格)。可以将数组(即,可以设置位置参数)初始化为当前目录中的文件名,如下所示:

set -- *
现在,位置参数数组保存文件名<代码>$#,元素数为三:

$ echo $#
3
我们可以用几种不同的方法迭代位置参数


1) 我们可以使用
$*

$ for file in $*; do
>    echo "$file"
> done
$ for file in "$*"; do
>    echo "$file"
> done
但这将空格和回音的争论重新区分了四次:

aaa
bbb
cc
c

2) 或者我们可以在
$*
周围加上引号:

$ for file in $*; do
>    echo "$file"
> done
$ for file in "$*"; do
>    echo "$file"
> done
但这会将整个数组分组为一个参数,并只调用一次echo:

aaa bbb cc c

3) 或者我们可以使用
$@
,它表示相同的数组,但在双引号中的行为不同:

$ for file in "$@"; do
>     echo "$file"
> done
将产生

aaa
bbb
cc c
因为$1=“aaa”、$2=“bbb”和$3=“cc c”和
“$@”
使元素保持不变。如果您在
$@
周围去掉引号,shell将展开并重新解析数组,echo将被调用四次,您将得到与裸
$*
相同的结果


这在shell脚本中特别有用,其中位置参数是传递给脚本的参数。要将这些相同的参数传递给其他命令,而不让shell在空白处重新填充它们,请使用
“$@”

在Bourne中,这种行为只适用于位置参数,因为它实际上是该语言支持的唯一数组。但是,您可以在Bash中创建其他数组,甚至可以使用特殊的
“${ARRAYNAME[@]}”
语法将旧的解析技巧应用于这些数组,其at符号对伯恩先生来说几乎像是眨眼:

$ declare -a myarray
$ myarray[0]=alpha
$ myarray[1]=bravo
$ myarray[2]="char lie"
$ for file in "${myarray[@]}"; do echo "$file"; done
alpha
bravo
char lie
哦,关于上一个示例,shell应该如何处理
“pre$@post”
,其中包含双引号中的
$@
,但也包含其他内容?Bash的最新版本保留数组,将
$@
前面的文本添加到第一个数组元素,并将
$@
后面的文本添加到最后一个元素:

pre aaa
bb
cc c post