【问题标题】:Associative array not unset when nullglob is set设置 nullglob 时关联数组未设置
【发布时间】:2019-06-24 12:57:42
【问题描述】:

当我在 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 上对此进行了测试。

【问题讨论】:

标签: bash associative-array glob quotes shopt


【解决方案1】:

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

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

如果没有找到匹配的文件名,并且 shell 选项 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 设置如何,这都会起作用,因为文档中有关引用的部分:

用单引号括起来的字符会保留引号内每个字符的字面值。

【讨论】:

  • 谢谢!如果没有 SO,我将无法编写 bash 脚本。我会花几个小时试图弄清楚这一点。有人对 nullglob 应该默认打开还是关闭有意见吗?
  • 只是 FTR,数组不必是关联的,这种奇怪现象就会发生。比较 shopt -u nullglob; a=(unset_me); unset a[0]; echo "${a[@]}"shopt -s nullglob; a=(unset_me); unset a[0]; echo "${a[@]}";完全一样的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 2020-07-04
  • 1970-01-01
相关资源
最近更新 更多