
我不明白為什麼 * 在沒有匹配項時會返回自身。這回答指出情況確實如此,但我不明白這種行為的基本原則。為什麼 * 或任何通用模式在不匹配的情況下不返回空字串?
$ls # Look, no files
$touch a # Add a file
$echo * # Works as expected
a
$rm a # Remove the file
$echo * # Will output a '*'. Why not ''?
*
$* # Ok, * will fail, but how come the previous output?
-bash: *: command not found
$
答案1
與任何文件都不匹配的模式被視為錯誤。您可以在 UNIX 的第一個版本中看到這一點。
全域會列印一個錯誤,並且它傳遞的命令永遠不會運作。
錯誤訊息是“不匹配”。
在你的現代外殼中源自Bourne(Unix 版本 7),ls -l *.c
會產生錯誤“*.c:沒有這樣的檔案或目錄”。我想說這個消息比較容易理解;它也指示失敗的模式。
請注意,如果*.c
擴展為空,ls -l *.c
則會顯示目錄中的所有文件,並且不會列印錯誤。
bash 有一個failglob
更接近原始行為的選項。
答案2
* 實際上是由 bash (無論你的 shell 是什麼)擴展的,然後它被傳遞到迴音。這迴音命令不執行任何操作,只是將其列印到標準輸出。閱讀本文檔 -檔案名稱擴充。它說-
Bash 掃描每個單字中的字元「*」、「?」和「[」。如果出現這些字元之一,則該單字被視為模式,並替換為與該模式相符的按字母順序排序的檔案名稱清單。如果沒有找到符合的檔案名,並且 shell 選項 nullglob 被停用,則該單字將保持不變。如果設定了 nullglob 選項,並且未找到匹配項,則該單字將被刪除。
所以實際上,當 bash 找不到任何匹配時,它會保留 '*' 不變,並 echo 打印出來。
原因
bash 預設不回傳空語句的原因是,在某些情況下,使用者不想使用「*」作為通配符,因此他不需要「*」的擴充。因此在這種情況下,將“*”擴展為空字串將是錯誤的。但是,可以透過選項覆寫此預設行為nullglob
。