Was machen `\ time`,` t \ ime` und `\ cd` eigentlich? (Spaß mit Backslashes in Muscheln)

9

Während der Diskussion über die Unterschiede zwischen /usr/bin/timeund der eingebauten Shell (bash und zsh) timeerwähnte jemand, dass man sie \timeals Abkürzung verwenden kann, um sie zu erhalten /usr/bin/time.

Zuerst schien es eine nette unschuldige Abkürzung zu sein, aber dann kamen einige Fragen auf:

  • Warum funktioniert t\imeauch?
  • Warum wird \cddas Verzeichnis geändert, obwohl /usr/bin/cd¹ dies nicht tut?

Also offensichtlich \fooist nicht gleichbedeutend mit $(which foo). Die Frage ist jetzt:

Wird das beobachtete Verhalten von \foosowohl in bash als auch in zsh in irgendeiner Weise von der POSIX-Definition einer Shell abgedeckt, und wenn ja, warum verhält es sich so?


Fußnote 1: /usr/bin/cdist auf meinem System

#!/bin/sh
builtin cd "$@"
Jonas Schäfer
quelle
Siehe auch unix.stackexchange.com/questions/12762/… Beachten Sie, dass \ command speziell für die tcsh-Funktionalität dokumentiert ist, die besagt, dass Aliase für den Befehl ignoriert werden sollen.
Simpleuser

Antworten:

14

t\imeoder \cd(oder "tim"eoder 'cd'oder ${-##*}timeoder ${-+time}und und jede andere Kombination von Zitaten und Erweiterungen, die Sie sich vorstellen können, würde sich irgendwann in timeoder auflösen cd), ist das: eine andere Art zu schreiben cdund time.

Dies würde sich jedoch irgendwann zu cdoder timezu einem späteren Zeitpunkt der Analyse und Interpretation der Shell-Syntax auflösen . Dies geschieht insbesondere lange nach der Erkennung von Shell-Schlüsselwörtern und der Alias- Ersetzung.

Wenn die Shell nach Schlüsselwörtern in ihrer Sprache sucht, wird sie nicht ti\meals timeShell-Schlüsselwort erkannt . Also a:

ti\me echo test

würde von der Shell als einfacher Befehl erkannt werden, im Gegensatz zum timeSchlüsselwort, gefolgt von einem einfachen Befehl.

Dann würde das Anführungszeichen ti\meverarbeitet (hier zitiert der Backslash das mZeichen, das ohnehin nicht zitiert werden muss, das Anführungszeichen wird entfernt, erhalten Sie time), und ein time Befehl würde wie alle anderen Befehle (in der Liste der eingebauten Befehle) nachgeschlagen , Funktionen und ausführbare Dateien in $PATH. Höchstwahrscheinlich wird das /bin/timehier sein)

Denn in der Shell-Sprache cdgibt es kein cdSchlüsselwort, nur einen cdeingebauten Befehl (der Vorrang vor Ihrem hat /usr/bin/cd). Wenn Sie jedoch einen Alias ​​für cd(like alias cd=pushd) definieren, wiederholen Sie dies erneut. Da die Aliasersetzung sehr früh vor dem Entfernen des Anführungszeichens erfolgt, wenn Sie einen Alias ​​für cdund keinen für haben \cd(beachten Sie, dass nicht viele Shells Aliase mit Backslashes zulassen), schreiben Sie Folgendes:

\cd dir

Sie stellen sicher, dass Ihr cdAlias ​​nicht ersetzt wird.

Kurz gesagt, zitierte einen Befehlsnamen oder einen Teil davon aus wird als Shell - Schlüsselwort gesehen verhindert (Keywords , die Dinge wie while, for, if, {... timeist ein Schlüsselwort in einigen Schalen nur) und umgeht einen Alias Sie es haben kann .

Es erzwingt jedoch nicht, dass dieser Befehl in eine ausführbare Datei aufgelöst $PATHwird. Der Befehl wird weiterhin zuerst zwischen Funktionen (die Sie umgehen können command time cmd...) und integrierten Funktionen (die Sie umgehen können env time cmd..., obwohl ich nichts weiß ) durchsucht eine Shell mit einem eingebauten timeBefehl).

Beachten Sie, dass das Zitieren auch das Verhalten der speziellen Buildins der typeset/ declare/ export/ local... -Familie in einigen Shells beeinflussen kann. Siehe Werden Anführungszeichen für die Zuweisung lokaler Variablen benötigt? für Details.

Stéphane Chazelas
quelle
Der Unterschied zwischen timeund cdwas zu dem Unterschied im beobachteten Verhalten führt, ist, dass timees sich um ein Schlüsselwort und cdeinen integrierten Befehl handelt .
Jonas Schäfer
1
@ JonasWielicki, das timeist ein Schlüsselwort und das cdnicht. (und wenn Sie einen Alias ​​für cdoder hätten time, wäre das eine andere Sache). Das cdist eingebaut oder hat an dieser Stelle keine Inzidenz (was den Einfluss des Zitierens betrifft). Einige Shells haben jedoch einige integrierte Funktionen, die sich auf halbem Weg zwischen Schlüsselwörtern und integrierten Funktionen befinden, da deren Analyse anders erfolgt als bei anderen integrierten Funktionen. Das ist der Fall von export/ typeset/ declare. Ich sollte in dieser Antwort wahrscheinlich einen Hinweis dazu hinzufügen.
Stéphane Chazelas