Zsh 將字串視為檔案名稱模式並抱怨它(NOMATCH 選項)

Zsh 將字串視為檔案名稱模式並抱怨它(NOMATCH 選項)

我正在嘗試來自 Bash 的 Zsh。我有點難以理解為什麼 Zsh 抱怨 grep 正規表示式。

usr@rk1 ~ % tty | grep ^/dev/tty[1-7]$ > /dev/null 2>&1
zsh: no matches found: ^/dev/tty[1-7]$

我注意到輸出消失了,如果(1)我將正則表達式放在引號內,(2)從正則表達式中刪除斜杠或(3)使用setopt NO_NOMATCH.

來自 zshoptions 手冊:

不符 (+3) <C> <Z>

如果檔案名稱產生模式沒有匹配項,則列印錯誤,而不是將其保留在參數清單中不變。這也適用於初始“~”或“=”的檔案擴充。

因此,在我看來,由於斜杠,正則表達式被視為檔案名稱模式。這被認為是正常現象還是錯誤?

另外,如果能有類似 GreyCat 的 Bashism 和 BashPitfalls 頁面但針對 Zsh 的東西那就太好了。你知道這樣的資源嗎?

答案1

如果您設定了該EXTENDED_GLOB選項,則該模式^something將用於檔案名稱產生。來自zshexpn手冊頁:

^x (需要設定 EXTENDED_GLOB。)符合模式 x 以外的任何內容。它的優先權高於/,因此^foo/bar將搜尋.除名./foo為 的檔案之外的目錄bar

因此,^/dev/tty[1-7]$正在嘗試在當前目錄的每個子目錄(不排除任何內容,因為^後面直接跟著)中查找名為, , .../的文件,該文件與 1 到 7 之間的範圍內的一個字符完全匹配。dev/tty1$dev/tty2$dev/tty7$[1-7]$

您已經找到了解決方案,設定NO_NOMATCH(可能很危險,但我非常喜歡它,因為我懶於打字;))或引用(單引號或雙引號)插入符號。

試試print正在發生的事情:

$ setopt nomatch extended_glob
$ echo ^/dev/tty[1-7]$
zsh: no matches found: ^/dev/tty[1-7]$

# ^ is doing filename generation in every sub-dir
$ touch foo/dev/tty5$
$ echo ^/dev/tty[1-7]$
foo/dev/tty5$

# quote to prevent filename generation
$ echo "^/dev/tty[1-7]$"
^/dev/tty[1-7]$
$ echo '^/dev/tty[1-7]$'
^/dev/tty[1-7]$

如果沒有EXTENDED_GLOB設置,插入符號將按字面解釋為普通字元。所以引用又是你的朋友了——這次只有[1-7]觸發檔名生成:

$ setopt nomatch no_extended_glob
$ echo ^/dev/tty[1-7]$
zsh: no matches found: ^/dev/tty[1-7]$

# quote to prevent filename generation
$ echo ^/dev/tty"[1-7]"$
^/dev/tty[1-7]$

# caret is interpreted literally
$ mkdir ^/dev -p
$ touch ^/dev/tty5$
$ echo ^/dev/tty[1-7]$
^/dev/tty5$

所以,總結一下:引用正規表示式模式對我來說似乎總是一個好主意——儘管我通常也會嘗試節省一些按鍵。

相關內容