Bash
為什麼 shopt -s nullglob 刪除數組元素中帶有問號的字元串?
這個小設置讓我發瘋:
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?
從數組元素中刪除了 ,但為什麼呢?該文件引用了可能包含*
and的文件名模式?
,但單獨的數組與“不匹配文件”無關: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
這意味著什麼?
當你這樣做
array=(foo bar?)
時,bar?
字元串是不加引號的,它包含文件名萬用字元?
(匹配任何單個字元)。這意味著 shell 將對這個值執行文件名通配。如果模式不匹配任何內容,則預設情況下保持原樣。如果它匹配某些東西(如bar1
、bar-
等bar.
),匹配的名稱將被插入到數組中。啟用後,如果沒有匹配的文件名,則完全刪除
nullglob
未引用的 globbing 模式bar?
(這通常是人們想要啟用的原因nullglob
)。這意味著您的數組,在這種情況下,將只包含foo
元素。換句話說,該
nullglob
設置將(除非您bar?
在目前目錄中呼叫了一個文件)阻止未引用的單詞bar?
甚至被分配為數組中的元素。如果你想要兩個字元串
foo
並bar?
在你的數組中,補救方法是引用它們(foo
不需要引用,但保持一致並沒有什麼壞處):array=('foo' 'bar?')
“解決”此問題的另一種方法是禁用文件名通配。這是通過以下方式完成的
set -f
:set -f array=(foo bar?) set +f
Michael 可能想要展示的
array=(*)
是,未引用的值(這裡是未引用的*
)會發生通配。他想展示這一點,因為這是你問題的根源。