我有以下示例脚本,想知道数组的长度到底是多少,是字节、字符还是其他什么?
#!/bin/bash
# Arrays
# @ vs. *
ape=( "Apple Banana" "Emacs Window" "Panda Bamboo Nature" )
cape=( 'Ping Pong' 'King Kong' 'King Fisher Club' 'Blurb' )
jade=( ally belly cally delly )
echo Expansion with \*
echo ${ape[*]}
echo ${cape[*]}
echo -e "${jade[*]}\n"
echo Expansion with \@
echo ${ape[@]}
echo ${cape[*]}
echo -e "${jade[@]}\n"
echo Elements with \*
echo ${#ape[*]}
echo ${#cape[*]}
echo ${#jade[*]}
echo Elements with \@
echo ${#ape[@]}
echo ${#cape[@]}
echo ${#jade[*]}
echo -e "\nLength"
echo ${#ape}
echo ${#cape}
echo ${#jade}
从我知道的手册页来看,如果该词是否用双引号引起来,则数组扩展与 to 不同*
,但我看不到任何差异。@
为什么我在这两种情况下得到相同的结果?
输出如下:
Expansion with *
Apple Banana Emacs Window Panda Bamboo Nature
Ping Pong King Kong King Fisher Club Blurb
ally belly cally delly
Expansion with @
Apple Banana Emacs Window Panda Bamboo Nature
Ping Pong King Kong King Fisher Club Blurb
ally belly cally delly
Elements with *
3
4
4
Elements with @
3
4
4
Length
12
9
4
答案1
*
您错过了它显示将数组扩展为单个字符串,并@
扩展为单独引用的字符串的情况:
printf 'string "%s"\n' "${cape[*]}"
这会产生
string "Ping Pong King Kong King Fisher Club Blurb"
和
printf 'string "%s"\n' "${cape[@]}"
这会产生
string "Ping Pong"
string "King Kong"
string "King Fisher Club"
string "Blurb"
请记住,echo
只是连接其参数并打印它们,而printf
将使用参数填充其格式字符串,并在提供更多参数时重复相同的格式。
还,
for s in "${cape[*]}"; do
echo "$s"
done
生成单行输出(它仅迭代单个字符串),而
for s in "${cape[@]}"; do
echo "$s"
done
每个数组元素生成一个。
${array[*]}
您总是希望在和扩展周围使用双引号${array[@]}
,除非您出于某种原因想要显式调用分词和文件名通配。您使用*
or@
取决于您是否需要将数组元素全部作为一个字符串,或者单独引用。
根据我的经验,很少使用[*]
.
当获取数组的长度时,使用哪个*
或哪个并不重要。@
但如果两者都不使用,您将获得数组第一个元素的字符长度。
答案2
根据您在变量赋值中使用的不同引用,我相信您将“如果该单词是否被双引号引起来”这句话误解为“如果数组元素被双引号引起来”,而手册意为“表示正在扩展的变量的单词是否用双引号引起来”。
您还可以使用echo
同一行上发生的变量扩展;如果您使用更可配置的东西,您可能会得到更清晰的结果,例如printf
(善行南达做到了),或作为:
$ printf -- '->%s<-\n' "${ape[@]}"
->Apple Banana<-
->Emacs Window<-
->Panda Bamboo Nature<-
如果您可以看到 printf 所做的中间值,您会看到:
printf -- '->%s<-\n' "Apple Banana" "Emacs Window" "Panda Bamboo Nature"
与未引用的版本相反:
$ printf -- '->%s<-\n' ${ape[@]}
->Apple<-
->Banana<-
->Emacs<-
->Window<-
->Panda<-
->Bamboo<-
->Nature<-
...其中中间值为:
printf -- '->%s<-\n' Apple Banana Emacs Window Panda Bamboo Nature
...这准确地显示了元素已扩展的内容。在第一种情况下,变量被引用,因此不会发生进一步的分词,并且您会得到三个元素。在第二种情况下,这三个元素中的每一个也会经历分词,所以printf
看到七要打印的元素。
数组的“长度”通常是使用语法生成的元素数量${#ape[@]}
。使用${#ape}
bash 询问第一个元素的长度:
引用不带下标的数组变量相当于引用下标为 0 的数组变量
这就是为什么你会得到这些不同的值。