Warum kann ich! (Einzelmuster) in zsh nicht verwenden, selbst nachdem ich kshglob eingeschaltet habe?

8

Dies funktioniert in Bash:

touch a b c
echo !(a)

Wenn ich das obige Skript in zsh (mit kshglobon) ausführe , beschwert es sich:

zsh: number expected

Wenn ich hinzufügen , |nach a, es funktioniert:

echo !(a|)

Warum?

dedowsdi
quelle

Antworten:

10

In diesem Fall kommt es zu Konflikten mit Bare-Glob-Qualifikatoren, da diese am Ende des Musters stehen. *(a1)wird als die Dateien verwendet, auf die am letzten Tag zuletzt zugegriffen wurde. (a1)wird als Glob-Qualifier behandelt. In Ihrem !(a)Fall beschwert sich zsh über die fehlende Anzahl von Tagen nach dem aGlob-Qualifikationsmerkmal (hier angewendet auf die aufgerufene Datei !).

In zshGlobs wird die (...)Gruppierung hauptsächlich für den (foo|bar)Wechsel verwendet. Das Hinzufügen von a |ist daher eine dokumentierte Methode, um sicherzustellen, dass ein Trailing (...)nicht als Glob-Qualifizierer behandelt wird.

Eine andere dokumentierte Alternative besteht darin, die Klammer ( !((a))) zu verdoppeln, oder Sie können ein leeres Glob-Qualifikationsmerkmal (wie !(a)(-)) hinzufügen .

Um diese Mehrdeutigkeit vollständig zu beseitigen, kann man die bare_glob_qualOption ( set +o bareglobqual) deaktivieren, wonach Glob-Qualifizierer mit der extendedglob (#q...)Syntax ( *(#qa1)hier) geschrieben werden müssen.

Die kshglobOption ( 1998 hinzugefügt , ungefähr zur gleichen Zeit bashhinzugefügt, extglobobwohl bash vorher keinen erweiterten Glob hatte) ist hauptsächlich für den kshEmulationsmodus ( emulate ksh) vorhanden, um Skripte zshausführen zu können ksh, wo kshglobaktiviert und bareglobqualdeaktiviert ist. Bei der ersten Einführung mussten Sie nach dem Aktivieren kshglobGlob-Qualifikationsmerkmale angeben -(...), um diese Art von Konflikten zu vermeiden. Dies führte jedoch zu zu viel Verwirrung und widersprach der @-(...)Syntax von ksh93, (#q...)und bareglobqualOptionen wurden später eingeführt.

zshBenutzer bevorzugen im Allgemeinen die erweiterten erweiterten glob ( set -o extendedglob) - Operatoren von zsh, die (für die meisten) einfacher einzugeben und leistungsfähiger sind (als die ksh88-Operatoren, die mit aktiviert kshglobsind bash -O extglob).

Zum Beispiel !(foo)würde geschrieben werden ^foo. Das !(foo|)barÄquivalent wäre jedoch länger wie (^(foo|))bar.

Andere ksh88 -> zsh Übersetzungen:

  • *(x) -> x#
  • +(x) -> x##
  • @(x|y) -> x|y
  • ?(x) -> (x|)

Einige ksh93 -> zsh Übersetzungen:

  • ~(i:x)-> (#i)x(Groß- und Kleinschreibung nicht berücksichtigen)
  • ~(N)x-> x(N)(nullglob, ursprünglich in zsh)
  • {1,5}(x) -> x(#c1,5)
  • @(foo&bar)-> foo~^baroder^(^foo|^bar)

Einige nur gefunden in zsh:

  • <1-23> (Bereich von Dezimalzahlen)
  • pattern~except
  • pattern(glob-qualifier) (das Killer-Feature von zsh globs)
  • (pattern/)#(Jede Ebene von Unterverzeichnissen, die mit übereinstimmen pattern; die **/vereinfachte Version von (*/)#wurde kürzlich auch zu ksh93 und bash hinzugefügt.)
  • ***/* (rekursives Globbing nach Symlinks).
  • (#a1)foobar (ungefähre Übereinstimmung, die einige Fehler zulässt, hier 1)
  • ...
Stéphane Chazelas
quelle