Wenn ich diese beiden Befehle ausführe, bekomme ich
$ type cd
cd is a shell builtin
$ type if
if is a shell keyword
Es wird deutlich gezeigt, dass cd
es sich um eine eingebaute Shell und if
ein Shell-Schlüsselwort handelt. Was ist der Unterschied zwischen Shell Builtin und Keyword?
command-line
Avinash Raj
quelle
quelle
Antworten:
Es gibt einen starken Unterschied zwischen einem eingebauten und einem Schlüsselwort, was die Art und Weise betrifft, wie Bash Ihren Code analysiert. Bevor wir über den Unterschied sprechen, listen wir alle Schlüsselwörter und Builtins auf:
Builtins:
Schlüsselwörter:
Beachten Sie, dass es sich beispielsweise
[
um ein eingebautes[[
Schlüsselwort handelt. Ich werde diese beiden verwenden, um den folgenden Unterschied zu veranschaulichen, da es sich um bekannte Operatoren handelt: Jeder kennt sie und verwendet sie regelmäßig (oder sollte).Ein Schlüsselwort wird von Bash sehr früh in der Analyse gescannt und verstanden. Dies ermöglicht zum Beispiel Folgendes:
Dies funktioniert gut, und Bash wird glücklich ausgeben
Beachten Sie, dass ich nicht zitiert habe
$string_with_spaces
. In der Erwägung, dasszeigt, dass Bash nicht glücklich ist:
Warum funktioniert es mit Schlüsselwörtern und nicht mit eingebauten? Denn wenn Bash den Code analysiert, sieht er,
[[
welches ein Schlüsselwort ist, und versteht sehr früh, dass es etwas Besonderes ist. Es wird also nach dem Verschluss suchen]]
und das Innere auf besondere Weise behandeln. Ein eingebauter (oder Befehl) wird als tatsächlicher Befehl behandelt, der mit Argumenten aufgerufen wird. In diesem letzten Beispiel geht bash davon aus, dass der Befehl[
mit Argumenten ausgeführt werden sollte (eines pro Zeile):da es zu variabler Erweiterung, Entfernung von Anführungszeichen, Erweiterung von Pfadnamen und Wortteilung kommt. Der Befehl
[
wird in der Shell erstellt, also führt er ihn mit diesen Argumenten aus, was zu einem Fehler und damit zur Beschwerde führt.In der Praxis sehen Sie, dass diese Unterscheidung ein ausgeklügeltes Verhalten ermöglicht, das mit integrierten Funktionen (oder Befehlen) nicht möglich wäre.
Wie kann man in der Praxis ein eingebautes von einem Schlüsselwort unterscheiden? Das ist ein lustiges Experiment:
Wenn Bash die Zeile analysiert
$a -d . ]
, sieht es nichts Besonderes (dh keine Aliase, keine Umleitungen, keine Schlüsselwörter), so dass es nur eine variable Erweiterung durchführt. Nach variablen Erweiterungen sieht es:Führt also den Befehl (builtin)
[
mit Argumenten aus-d
,.
und]
das ist natürlich wahr (dies testet nur, ob.
es sich um ein Verzeichnis handelt).Schau jetzt:
Oh. Das liegt daran, dass Bash, wenn er diese Zeile sieht, nichts Besonderes sieht und daher alle Variablen erweitert und schließlich sieht:
Zu diesem Zeitpunkt wurden Alias-Erweiterungen und das Durchsuchen von Schlüsselwörtern schon lange durchgeführt und werden nicht mehr durchgeführt. Bash versucht daher, den aufgerufenen Befehl zu finden
[[
, findet ihn nicht und beschwert sich.Auf der gleichen Linie:
und
Auch die Alias-Erweiterung ist etwas Besonderes. Sie haben alle mindestens einmal Folgendes getan:
Die Überlegung ist dieselbe: Die Alias-Erweiterung erfolgt lange vor der variablen Erweiterung und der Entfernung von Anführungszeichen.
Keyword vs Alias
Was passiert Ihrer Meinung nach, wenn wir einen Alias als Schlüsselwort definieren?
Oh, es funktioniert! Aliase können also verwendet werden, um Keywords zu aliasen! gut zu wissen.
Fazit: Builtins verhalten sich wirklich wie Befehle: Sie entsprechen einer Aktion, die mit Argumenten ausgeführt wird, die einer direkten Variablenerweiterung, Wortteilung und Globbing unterzogen werden. Es ist wirklich wie in einem externen Befehl irgendwo mit
/bin
oder/usr/bin
dass mit den Argumenten nach variable Expansion gegeben genannt wird, usw. Beachten Sie, dass , wenn ich sage , es ist wirklich wie ein externer Befehl, die ich nur mit Bezug auf Argumente, einzelne Wörter aufgespalten, bedeuten Globbing, variable Erweiterung, etc. Ein Builtin kann den internen Zustand der Shell verändern!Andererseits werden Schlüsselwörter sehr früh gescannt und verstanden und ermöglichen ein ausgeklügeltes Shell-Verhalten: Die Shell kann die Aufteilung von Wörtern oder die Erweiterung von Pfadnamen usw. verbieten.
Schauen Sie sich nun die Liste der integrierten Funktionen und Schlüsselwörter an und versuchen Sie herauszufinden, warum einige Schlüsselwörter sein müssen.
!
ist ein Schlüsselwort. Es scheint möglich zu sein, sein Verhalten mit einer Funktion nachzuahmen:aber das würde Konstrukte wie verbieten:
oder
Dasselbe gilt für
time
: Es ist leistungsfähiger, ein Schlüsselwort zu haben, damit komplexe zusammengesetzte Befehle und Pipelines mit Umleitungen zeitlich festgelegt werden können:Wenn
time
nur ein Befehl (auch eingebaut) vorhanden wäre, würden nur die Argumente angezeigtgrep
,^#
und zu gegebener/home/gniourf/.bashrc
Zeit würde seine Ausgabe die verbleibenden Teile der Pipeline durchlaufen. Aber mit einem Schlüsselwort kann Bash alles bewältigen! es kanntime
die komplette pipeline inklusive der umleitungen! Wenntime
es nur ein Befehl wäre, könnten wir Folgendes nicht tun:Versuch es:
Versuch es zu reparieren:
Hoffnungslos.
Keyword gegen Alias?
Was denkst du passiert?
In Wirklichkeit ist ein Builtin wie ein Befehl, nur dass er in die Shell integriert ist, während ein Schlüsselwort ein ausgefeiltes Verhalten zulässt! Wir können sagen, dass es Teil der Grammatik der Shell ist.
quelle
=\
'durch die Verwendungman
,apropos
undhelp
ich habe nicht hatte kein Glück. Irgendeine Idee, wo ich diese Informationen finden würde? Meistens, damit ich in Zukunft sehen kann, was sonst noch drin ist, weil ich glaube, dass ich eine Referenzquelle vermisse.\ll
,"ll"
oder'll'
.[[
Ergebnis zitieren , wird\[[
es nicht als Alias analysiert. Bis jetzt richtig? Als ich mich verlaufen habe, war mir nicht klar, dass der Backslash in Bash ein Zitat ist, und ich habe versucht, ihn unter Aliasnamen und Schlüsselwörtern nachzuschlagen und bin völlig verloren gegangen ... Alles gut jetzt. Im Abschnitt Zitieren:> Ein nicht in Anführungszeichen stehender Backslash () ist das Escape-Zeichen.\[[
Tokenization vorstellen und stellen ein einzelnes Token vom Typ LiteralQuoteToken vor, im Gegensatz[[
zu einem OpenTestKeywordToken,]]
für dessen Kompilierung / korrekte Syntax CloseTestKeywordToken erforderlich ist . Später wird in (4) das LiteralQuoteToken[[
als Name des auszuführenden Befehls ausgewertet , und in (6) wird Bash gesperrt, weil es keinen[[
eingebauten Befehl gibt. Nett. Ich kann die genauen Details im Laufe der Zeit vergessen, aber in diesem Moment ist mir die Art und Weise, wie Bash Dinge ausführt, viel klarer. Danke dir.man bash
ruft sie anSHELL BUILTIN COMMANDS
. Eine "eingebaute Shell" ist also wie ein normaler Befehlgrep
usw., aber anstatt in einer separaten Datei enthalten zu sein, ist sie in bash selbst eingebaut . Dadurch arbeiten sie effizienter als externe Befehle.Ein Schlüsselwort ist auch "fest in Bash codiert, aber im Gegensatz zu einem eingebauten Schlüsselwort ist ein Schlüsselwort an sich kein Befehl, sondern eine Untereinheit eines Befehlskonstrukts." Ich interpretiere dies so, dass Schlüsselwörter allein keine Funktion haben, aber Befehle erfordern, um etwas zu tun. (Aus dem Link, weitere Beispiele sind
for
,while
,do
, und!
, und es gibt mehr in meiner Antwort auf Ihre andere Frage.)quelle
[[ is a shell keyword
aber[ is a shell builtin
. Ich habe keine Idee warum.[
früher als separater Befehl existierte.[[
Wird vom Standard nicht spezifiziert, so können die Entwickler wählen, ob sie das als Schlüsselwort oder als eingebautes Schlüsselwort verwenden möchten.Das mit Ubuntu gelieferte Befehlszeilenhandbuch enthält keine Definition von Schlüsselwörtern. Das Online-Handbuch (siehe Abschnitt) und die Standardspezifikationen für POSIX Shell Command Language bezeichnen diese als "Reserved Words" (Reservierte Wörter) und enthalten beide Listen. Aus dem POSIX-Standard:
Der Schlüssel hier ist, dass Schlüsselwörter / reservierte Wörter eine besondere Bedeutung haben, da sie die Shell-Syntax erleichtern, dazu dienen, bestimmte Codeblöcke wie Schleifen, zusammengesetzte Befehle, Verzweigungsanweisungen (if / case) usw. zu signalisieren. Sie ermöglichen jedoch die Bildung von Befehlsanweisungen selbst - tut nichts, und in der Tat , wenn Sie eingeben Schlüsselwörter wie
for
,until
,case
- die Hülle eine vollständige Erklärung erwarten, andernfalls - Syntaxfehler:Auf Quellcode-Ebene werden die reservierten Wörter für bash in parese.y definiert , während den eingebauten Wörtern das gesamte Verzeichnis zugeordnet ist.
Randnotiz
Der GNU-Index wird
[
als reserviertes Wort angezeigt, es handelt sich jedoch um einen eingebauten Befehl.[[
dagegen ist ein reserviertes Wort.Siehe auch: Unterschiede zwischen Schlüsselwort, reserviertem Wort und eingebautem?
quelle