设置nullglob时未设置Bash关联数组

时间:2019-01-31 06:01:18

标签: bash associative-array glob quotes array-unset

当我在bash中设置nullglob时:

shopt -s nullglob

,然后声明一个关联数组:

declare -A arr=( [x]=y )

我无法取消设置数组中的特定键:

unset arr[x]
echo ${#arr[@]} # still 1

但是,取消设置nullglob会使此操作按我的预期进行:

shopt -u nullglob
unset arr[x]
echo ${#arr[@]} # now it's 0; x has been removed

这是怎么回事?我不知道外壳的变化与情况如何相关。我已经在bash 4.4.19和5.0.0上进行了测试。

1 个答案:

答案 0 :(得分:3)

这可以通过参考bash文档(man页)进行解释,解释如下:

  

单词拆分后,除非设置了-f选项,否则Bash会在每个单词中扫描字符'*''?''['。如果出现这些字符之一,则将该单词视为一个模式,并替换为与该模式匹配的按字母顺序排序的文件名列表。

     

如果未找到匹配的文件名,并且禁用了外壳程序选项nullglob,则该词保持不变。如果设置了nullglob选项,但没有找到匹配项,则会删除该单词。

换句话说,nullglob影响您的arr[x]自变量会发生什么。它将被保留或被删除。

通过使用set -x打开echo-before-execute标志,您可以看到这种效果:

pax$ declare -A arr=( [x]=y )
pax$ shopt -s nullglob
pax$ set -x
pax$ unset arr[x]
+ unset

请注意,这是“单词已删除”的情况。这样就显示了“单词保持不变”的情况:

pax$ shopt -u nullglob
+ shopt -u nullglob
pax$ unset arr[x]
+ unset 'arr[x]'

上面的最后一条回显命令还提供了有关在启用nullglob的情况下如何删除条目的线索。只需引用参数以防止扩展:

unset 'arr[x]'

由于文档中有关引用的部分,因此无论nullglob设置如何,该方法均有效:

  

将字符括在单引号中可保留引号内每个字符的字面值。