bash中数组的语义

bash中数组的语义,bash,shell,Bash,Shell,请查看以下成绩单。在所有可能的严格和正式的情况下,每一步都在进行什么 $> ls -1 #This command prints 3 items. no explanation required. a b c $> X=$(ls -1) #Capture the output (as what? a string?) $> Y=($(ls -1)) #Capture it again (as an array now?) $> echo ${#X[@]} #Wh

请查看以下成绩单。在所有可能的严格和正式的情况下,每一步都在进行什么

$> ls -1 #This command prints 3 items. no explanation required.
a
b
c

$> X=$(ls -1) #Capture the output (as what?  a string?)

$> Y=($(ls -1))  #Capture it again (as an array now?)

$> echo ${#X[@]} #Why is the length 1?
1

$> echo ${#Y[@]} #This works because Y is an array of the 3 items?
3

$> echo $X #Why are the linefeeds now spaces?
a b c

$> echo $Y  #Why does the array echo as its first element
a

$> for x in $X;do echo $x; done #iterate over $X
a
b
c

$> for y in $Y;do echo $y; done #iterating over y doesn't work
a

$> echo ${X[2]}  #I can loop over $X but not index into it?

$> echo ${Y[2]} #Why does this work if I can't loop over $Y?
c

我假设bash对数组和文本变量(如果它们被称为)的工作方式有很好的语义,但是,对于那些想根据语言设计师想要的任何一小部分基本原则来推理脚本的人来说,用户手册的组织方式并不是最佳的。

让我在下面的序言中提出一个非常强烈的建议,即决不使用
ls
来填充数组。正确的代码应该是

Z=( * )
使用当前目录中的每个(非隐藏)文件作为不同的数组元素创建数组

$> echo ${#X[@]} #Why is the length 1?
1

对。每个文件名都打印在单独的一行上(不过,请注意包含换行符的文件名;每个换行符之前和之后的部分将显示为单独的文件名。)

对。
ls
的输出通过命令替换连接成单个字符串,使用单个空格分隔每行。(如果不是赋值的右侧,则命令替换将进行分词;分词将出现在下面。)

与X相同,但现在命令替换结果中的每个字都被视为一个单独的数组元素。只要输出行中没有一行包含
IFS
值中的任何字符,每个文件名都是一个单词,将被视为一个单独的数组元素

$> echo ${#X[@]} #Why is the length 1?
1
X
不是一个真正的数组,它被视为一个包含单个元素的数组,即
$X
的值

$> echo ${#Y[@]} #This works because Y is an array of the 3 items?
3

$> echo $X #Why are the linefeeds now spaces?
a b c
$X
未加引号时,生成的扩展将进行分词。在这种情况下,换行符被简单地视为与任何其他空格相同的内容,将结果分隔为一系列单词,这些单词作为不同的参数传递给
echo
,然后以单个空格分隔显示

$> echo $Y  #Why does the array echo as its first element
a
对于真数组,
$Y
相当于
${Y[0]}

$> for x in $X;do echo $x; done #iterate over $X
a
b
c
这是可行的,但有一些警告

$> for y in $Y;do echo $y; done #iterating over y doesn't work
a
见上文<代码>$Y仅扩展到第一个元素。您想在“${y[@]}”中为y添加
;执行
迭代所有元素

$> echo ${X[2]}  #I can loop over $X but not index into it?
X
不是数组,而是扩展为一个空格分隔的列表,
for
循环可以迭代该列表

$> echo ${Y[2]} #Why does this work if I can't loop over $Y?
c
在shell中,索引和迭代是两件完全不同的事情。实际上,您并没有迭代数组;在正确扩展数组的结果字序列上迭代

$> echo ${X[2]}  #I can loop over $X but not index into it?
$> echo ${Y[2]} #Why does this work if I can't loop over $Y?
c