Beliebt

Zsh behandelt einen String als Dateinamenmuster und beschwert sich darĂŒber (Option NOMATCH) - zsh

Ich probiere Zsh aus und komme aus Bash. Ich hatte ein bisschen MĂŒhe zu verstehen, warum Zsh sich ĂŒber einen Grep-Regex beschwert.

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

Ich habe festgestellt, dass die Ausgabe verschwindet und alles in Ordnung ist, wenn (1) ich den Regex in AnfĂŒhrungszeichen setze, (2) die SchrĂ€gstriche vom Regex entferne oder (3) verwende setopt NO_NOMATCH.

Aus dem Handbuch von zshoptions:

NOMATCH (+3) <C> <Z>

Wenn ein Muster fĂŒr die Dateinamengenerierung keine Übereinstimmungen aufweist, drucken Sie einen Fehler, anstatt ihn in der Argumentliste unverĂ€ndert zu lassen. Dies gilt auch fĂŒr die Dateierweiterung eines anfĂ€nglichen "~" oder "=".

Es scheint mir, dass der regulÀre Ausdruck aufgrund der SchrÀgstriche als Dateinamenmuster behandelt wird. Ist das normal oder ein Fehler?

Es wĂ€re auch großartig, wenn Sie etwas Ähnliches wie die Seiten Bashism und BashPitfalls von GreyCat, aber fĂŒr Zsh, hĂ€tten. Kennen Sie eine solche Ressource?

Antworten:

1 fĂŒr Antwort № 1

Wenn Sie das eingestellt haben EXTENDED_GLOB Option, das Muster ^something wird zur Erzeugung von Dateinamen verwendet. Von dem zshexpn Manpage:

^x (Erfordert das Setzen von EXTENDED_GLOB.) Stimmt mit nichts außer ĂŒberein das Muster x. Dies hat eine höhere PrioritĂ€t als /, so ^foo/bar durchsucht Verzeichnisse in . außer ./foo fĂŒr eine Datei mit dem Namen bar.

So, ^/dev/tty[1-7]$ versucht in jedem Unterverzeichnis zu finden (nichts ist ausgeschlossen, weil ^ wird direkt gefolgt von /) des aktuellen Verzeichnisses fĂŒr eine Datei mit dem Namen dev/tty1$, dev/tty2$, ..., dev/tty7$ wie [1-7] stimmt mit genau einem Zeichen im Bereich zwischen 1 und 7 ĂŒberein. $ wird in diesem Fall nicht besonders behandelt.

Du hast schon die Lösung gefunden, eingestellt NO_NOMATCH (mag gefĂ€hrlich sein, aber ich mag es sehr, da ich faul im Tippen bin ;)) oder Zitat (einfache oder doppelte AnfĂŒhrungszeichen) das Caret.

Versuche es mit print Was ist los:

$ 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]$

Ohne EXTENDED_GLOB gesetzt, wird das Caret buchstÀblich als normales Zeichen interpretiert. Also ist das Zitieren wieder dein Freund - diesmal nur der [1-7] Löst die Dateinamengenerierung aus:

$ 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$

Fazit: Das Zitieren von Regex-Mustern scheint mir immer eine gute Idee zu sein - obwohl ich normalerweise auch versuche, einige TastenanschlÀge zu speichern.