Während der Diskussion über die Unterschiede zwischen /usr/bin/time
und der eingebauten Shell (bash und zsh) time
erwähnte jemand, dass man sie \time
als 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\ime
auch? - Warum wird
\cd
das Verzeichnis geändert, obwohl/usr/bin/cd
¹ dies nicht tut?
Also offensichtlich \foo
ist nicht gleichbedeutend mit $(which foo)
. Die Frage ist jetzt:
Wird das beobachtete Verhalten von \foo
sowohl 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/cd
ist auf meinem System
#!/bin/sh
builtin cd "$@"
shell
quoting
posix
time-utility
Jonas Schäfer
quelle
quelle
Antworten:
t\ime
oder\cd
(oder"tim"e
oder'cd'
oder${-##*}time
oder${-+time}
und und jede andere Kombination von Zitaten und Erweiterungen, die Sie sich vorstellen können, würde sich irgendwann intime
oder auflösencd
), ist das: eine andere Art zu schreibencd
undtime
.Dies würde sich jedoch irgendwann zu
cd
odertime
zu 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\me
alstime
Shell-Schlüsselwort erkannt . Also a:würde von der Shell als einfacher Befehl erkannt werden, im Gegensatz zum
time
Schlüsselwort, gefolgt von einem einfachen Befehl.Dann würde das Anführungszeichen
ti\me
verarbeitet (hier zitiert der Backslash dasm
Zeichen, das ohnehin nicht zitiert werden muss, das Anführungszeichen wird entfernt, erhalten Sietime
), und eintime
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/time
hier sein)Denn in der Shell-Sprache
cd
gibt es keincd
Schlüsselwort, nur einencd
eingebauten Befehl (der Vorrang vor Ihrem hat/usr/bin/cd
). Wenn Sie jedoch einen Alias fürcd
(likealias 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ürcd
und keinen für haben\cd
(beachten Sie, dass nicht viele Shells Aliase mit Backslashes zulassen), schreiben Sie Folgendes:Sie stellen sicher, dass Ihr
cd
Alias 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
,{
...time
ist 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
$PATH
wird. Der Befehl wird weiterhin zuerst zwischen Funktionen (die Sie umgehen könnencommand time cmd...
) und integrierten Funktionen (die Sie umgehen könnenenv time cmd...
, obwohl ich nichts weiß ) durchsucht eine Shell mit einem eingebautentime
Befehl).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.quelle
time
undcd
was zu dem Unterschied im beobachteten Verhalten führt, ist, dasstime
es sich um ein Schlüsselwort undcd
einen integrierten Befehl handelt .time
ist ein Schlüsselwort und dascd
nicht. (und wenn Sie einen Alias fürcd
oder hättentime
, wäre das eine andere Sache). Dascd
ist 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 vonexport
/typeset
/declare
. Ich sollte in dieser Antwort wahrscheinlich einen Hinweis dazu hinzufügen.