这个小设定让我抓狂:
shopt -s nullglob
我在 bash 4.3 脚本中使用它作为全局设置避免扫描空目录时出错。
现在我发现了一个我不明白的奇怪问题:
# shopt -s nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo
# shopt -u nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo bar?
正如您所看到的,它bar?
从数组元素中删除了 ,但为什么呢?这文档指的是可以包含*
和 的文件名模式?
,但单独的数组与“不匹配文件”无关:
If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves.
这是一个错误吗?
PS 我将在循环周围设置/取消设置 nullglob 来解决我的问题。这不是问题!
更新1
正如@MichaelHomer 所要求的:
# shopt -s nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1
# shopt -u nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1
这意味着?
答案1
当您这样做时array=(foo bar?)
,该bar?
字符串不带引号,并且包含文件名通配字符?
(与任何单个字符匹配)。这意味着 shell 将对此值执行文件名通配。如果模式不匹配任何内容,则默认情况下保持原样。如果它匹配某些内容(例如bar1
、等),bar-
则bar.
匹配的名称将被插入到数组中。
启用后,如果没有文件名与其匹配,nullglob
则不带引号的通配模式将被完全删除(这通常是人们想要启用的原因)。这意味着在这种情况下,您的数组将仅包含该元素。bar?
nullglob
foo
换句话说,该设置将(除非您在当前目录中nullglob
调用了一个文件)甚至阻止将未加引号的单词指定为数组中的元素。bar?
bar?
如果您想要两个字符串foo
和bar?
在数组中,补救措施是引用它们(foo
不需要引用,但保持一致不会有什么坏处):
array=('foo' 'bar?')
“解决”这个问题的另一种方法是禁用文件名通配。这是通过以下方式完成的set -f
:
set -f
array=(foo bar?)
set +f
Michael 可能想展示的array=(*)
是,未加引号的值(此处为未加引号的*
)会发生通配。他想展示这一点,因为这是问题的根源。