我最近发现你无法将空字符串传递给 Bash 数组。这很棘手,因为我试图将空字符串值插入到数组中。
然而,我注意到 Bash 完成变量 COMP_WORDS 可以包含空值。
我编写了一个虚拟完成脚本来说明这一点,并启用了调试选项:
1 #!/bin/bash
2 _comp() {
3 set -xv
4 for i in ${!COMP_WORDS[@]}; do
5 echo "<${COMP_WORDS[$i]}>"
6 done
7 set +xv
8 local cur=${COMP_WORDS[$COMP_CWORD]}
9
10 local arr=(apple banana mango pineapple)
11 COMPREPLY=()
12 COMPREPLY=($(compgen -W "${arr[*]}" -- $cur))
13
14 }
15
16 complete -F _comp dummy
如果我获取该文件,然后输入以下内容:
dummy apple banana
然后,如果我将光标移回苹果和香蕉之间的中间空间(下面用下划线表示)...
dummy apple _ banana
然后,如果我点击选项卡,我会从生成的调试中得到以下输出,显示四个数组元素,'dummy''apple''''banana'
for i in '${!COMP_WORDS[@]}'
+ echo '<dummy>'
<dummy>
+ for i in '${!COMP_WORDS[@]}'
+ echo '<apple>'
<apple>
+ for i in '${!COMP_WORDS[@]}'
+ echo '<>'
<>
+ for i in '${!COMP_WORDS[@]}'
+ echo '<banana>'
<banana>
因此 COMP_WORDS 数组显然能够存储某种空字符串。尽管有趣的是,这确实不是如果我使用常规的 for 循环,访问数组元素而不是索引,就会发生这种情况。即,如果我将调试部分中的 for 循环更改为此...
for i in ${COMP_WORDS[@]}; do
echo "<$i>"
done
然后我得到以下调试输出,仅显示三个数组元素: 'dummy' 'apple' 'banana'
for i in '${COMP_WORDS[@]}'
+ echo '<dummy>'
<dummy>
+ for i in '${COMP_WORDS[@]}'
+ echo '<apple>'
<apple>
+ for i in '${COMP_WORDS[@]}'
+ echo '<banana>'
<banana>
我尝试用 - 来回显数组的长度${#COMP_WORDS[@]}
- 对于此输入,它显示的长度为四。所以它显然包含四个元素,其中一个是空字符串。
对我来说,这似乎是非常奇怪的行为。我的问题有两个:
当普通数组显然不能存储空字符串时,COMP_WORDS 数组能够存储空字符串的解释是什么?
为什么当我使用常规 for 循环时看不到空字符串,但当我通过索引访问数组元素时却可以看到它?
答案1
您似乎将空字符串""
与 NULL 字符混淆了\0
。他们不一样。您可以在数组和变量中使用空字符串:
$ a=(aa "" "b")
$ echo "${#a[@]}"
3
$ printf -- '- %s\n' "${a[@]}"
- aa
-
- b
$ for i in "${a[@]}"; do
> printf '%s\n' "$i"
> done
aa
b
一些条件表达式在 Bash 中甚至允许测试字符串是否为空:
-z 字符串
True if the length of string is zero.
-n 字符串 字符串
True if the length of string is non-zero.
也可以看看什么时候需要双引号?