Bash

為什麼 shopt -s nullglob 刪除數組元素中帶有問號的字元串?

  • August 11, 2019

這個小設置讓我發瘋:

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 將對這個值執行文件名通配。如果模式不匹配任何內容,則預設情況下保持原樣。如果它匹配某些東西(如bar1bar-bar.),匹配的名稱將被插入到數組中。

啟用後,如果沒有匹配的文件名,則完全刪除nullglob未引用的 globbing 模式bar?(這通常是人們想要啟用的原因nullglob)。這意味著您的數組,在這種情況下,將只包含foo元素。

換句話說,該nullglob設置將(除非您bar?在目前目錄中呼叫了一個文件)阻止未引用的單詞bar?甚至被分配為數組中的元素。

如果你想要兩個字元串foobar?在你的數組中,補救方法是引用它們(foo不需要引用,但保持一致並沒有什麼壞處):

array=('foo' 'bar?')

“解決”此問題的另一種方法是禁用文件名通配。這是通過以下方式完成的set -f

set -f
array=(foo bar?)
set +f

Michael 可能想要展示的array=(*)是,未引用的值(這裡是未引用的*)會發生通配。他想展示這一點,因為這是你問題的根源。

引用自:https://unix.stackexchange.com/questions/534858