3

当我在 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

这里发生了什么?我不明白 shell globbing 与这种情况有何关系。我已经在 bash 4.4.19 和 5.0.0 上对此进行了测试。

4

1 回答 1

5

这可以通过参考bash文档(man页面)来解释,在这里解释:

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

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

换句话说,nullglob影响你的arr[x]论点会发生什么。它将被单独放置或删除。

您可以通过使用以下命令打开 echo-before-execute 标志来查看此效果set -x

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设置如何,这都将起作用,因为文档中有关引用的部分:

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

于 2019-01-31T06:18:19.410 回答