Der folgende Befehl funktioniert beispielsweise nicht:
if [[-e xyz]]; then echo File exists;fi
ksh gibt den folgenden Fehler aus
[[-e: command not found
Liegt das daran, dass "[[-" nicht eindeutig ist?
command-line
syntax
ksh
Myloti
quelle
quelle
[[
ist ein Schlüsselwort - vermutlich erfordert derAntworten:
Die einfachste Erklärung wäre, weil es im Handbuch so aussieht, als müsste
[[ expression ]]
zwischen[[
undexpression
und Schließen ein Leerzeichen sein]]
. Aber natürlich können wir versuchen, es genauer zu betrachten. Muscheln haben eine etwas komplexe Grammatik und stützen sich stark auf das Konzept der "Wortteilung". Im Handbuch von ksh (1) heißt es insbesondere:Wie im Handbuch angegeben, wird die Zeichenfolge
[[-e
als Shell-Wort betrachtet.ksh
würde nach einem solchen Befehl in der Liste der eingebauten und speziellen Operatoren (wiefor
oderwhile
) suchen und dann nach einem externen Befehl suchen - und voilà - keiner gefunden, daher gibt es eine Fehlermeldung über den Befehl nicht gefunden.In diesem Fall handelt
[[
es sich auch nicht um spezielle Metazeichen. Wenn dies der Fall wäre, würde der-e
Teil in[[-e
als Shell-Wort betrachtet, nicht als Argument für[[
sich. Wird[[
jedoch als zusammengesetzter Befehl beschrieben, und das Handbuch sagt Folgendes aus:Um
[[
als zusammengesetzter Befehl erkannt zu werden, muss es ein erstes Wort eines Befehls oder einer Befehlsliste sein, was nach vorheriger Definition eines "Wortes" impliziert, dass es durch Leerzeichen, Tabulatoren oder Zeilenumbrüche von anderen getrennt werden muss Wörter / Argumente.Sie haben in den Kommentaren gefragt : "Warum kann der Parser nicht anhalten, sobald er das Muster" [["findet und dies als Beginn eines bedingten Befehls behandelt?" Eine kurze Antwort ist wahrscheinlich, weil 1) der Einfluss der
[
Syntax, da es sich ursprünglich um einen externen Befehl handelte, und für POSIX-Standards die Konformität auch heute noch als externer Befehl besteht, und 2) weil der Shell-Parser so aufgebaut ist. Der Shell-Parser kann andere nicht durch Leerzeichen getrennte Sonderzeichen erkennenecho $((2+2))
und(echo foobar)
funktioniert einwandfrei. Vielleicht wird in Zukunft, wenn dieksh
Entwicklung wieder aufgenommen wird oder es einen Fork oder Klon (wiemksh
oderpdksh
) gibt, jemand eine platzlose Syntax implementieren[[-e
.Siehe auch:
[[
es als "reserviertes Wort" bezeichnet (siehe Abschnitt 2.9 der Shell-Befehlssprache ). Gemäß der POSIX-Definition muss das reservierte Wort durch Leerzeichen begrenzt werden. Im Gegensatz dazu(
handelt es sich um einen Operator, und die Standardzustände in Abschnitt 2.9 "Die Darstellungen enthalten Abstände zwischen Token an einigen Stellen, an denen<blank>
s nicht erforderlich wäre (wenn einer der Token ein Operator ist)." Siehe verwandte Diskussion: POSIX-Shell-Grammatik: Warum benötigt die Brace-Gruppe den ersten Platz, die Subshell jedoch nicht?quelle
char
ist es ein Schlüsselwort, aber Sie können immer noch nicht schreibencharsomeletter = 'A';
und erwarten , dass der Parser nach dem Anzeigen stopptchar
.i--<=++j
, und der Compiler hat kein Problem damit, das als zu analysiereni -- <= ++ j
._
). Ksh hat(
als Operator und(echo hello)
analysiert als( echo hello )
. Es hat sichif
,{
,[[
und andere Schlüsselwörter , undifx
,{x
und[[x
jeweils ein Token - wie , wiecharsomeletter
ist ein C - Token. Im Gegensatz dazu besteht ein(x
in ksh nicht zitiertes Zeichen aus zwei Token - genau wiei--
zwei Token in C. Was es konzeptionell sogar bedeutet , ein Operator zu sein, unterscheidet sich zwischen Bourne-Shells (wie ksh) und C. Peter A. Schneider wies jedoch auf a hin echte lexikalische Ähnlichkeit.Es ist wichtig zu beachten, dass
[
es sich um einen Befehl handelt und das Shell-Schlüsselwort[[
in bash und ksh auf basiert[
.[[
wird in ähnlicher Weise verwendet wie[
. Manchmal kann man sogar ersetzen[
]
mit[[
]]
ohne Änderung im Verhalten. Mit[
wie jeder Befehl ist ein Raum zwischen dem Befehl und seine Argumente obligatorisch. Gleiches gilt für[[
.Früher hatten wir nur
/usr/bin/[
. Jetzt haben[
die meisten Shells aus Effizienzgründen eingebaut - aber die Syntax ist dieselbe. In Muscheln, die bieten[[
, fungiert es als vielseitigere Alternative zu[
.Hier ist die Beschreibung für
[
in bash:Ist
[
also gleichbedeutend mittest
(abgesehen davon, dass]
am Ende ein Argument erwartet wird ).help test
wird noch mehr Details dazu geben. Sie können dies mit vergleichenhelp [[
.Es gibt auch eine Manpage für den externen Befehl
[
(man \[
).Im Falle des
[
noch[[
ist ein Befehl da. Das ganze Wort[[-e
ist.if [[-e
macht es zu einem Test für wahr / falsch. Existiert also ein Befehl[[-e
?Ja. Oder Nein.
[[-e
ist, was es ist: nichts, was die Shell versteht, also nimmt sie an, dass es ihr eigener Befehl ist. ;-);quelle
[[-e
ist ein potenziell gültiger (wenn auch seltsam aussehender) Befehlsname.Der Raum ist ein Begrenzer und wird benötigt. Wie Sie sehen können aus
shellcheck
:(Sowohl ksh als auch bash unterstützen
[[
und funktionieren nicht ohne Leerzeichen. Shellcheck liefert genau diese Ausgabe mit ähnlichen ksh- und bash-Skripten, die diese fehlerhafte Zeile enthalten.)Warum Deliminatoren benötigt werden, hat mit Token und Lexika zu tun .
quelle
ksh
in der Frage nach Shell gefragt hat. Bash leiht[[
Operator vonksh
und in dieser Frage ist ihr Verhalten identisch, aber ich würde vorsichtig mit Annahmen sein, da es einige signifikante Unterschiede zwischenksh
undbash
Verhalten und Interna gibt. Das liegt nur daran, dass Shellcheck mit Bash-Skripten funktioniert. Es ist möglicherweise nicht unbedingt das geeignete Tool für Ksh-Skripte. Nur etwas zu beachten, wenn Sie sich verschiedenen Muscheln nähern[[
integrierten Regeln hervorzuheben . Ich habe in keiner Weise gefolgert, dassksh
es sich um eine Shell handelt,shellcheck
in der Fehler gefunden werden können. Ich hoffe, andere schätzenksh
undbash
sind zwei verschiedene Interpreten. Danke, dass Sie das erwähnt haben. Erwähnenswert[[
ist auch eine eingebaute Bash, während[
es sich um einen externen Befehl handelt.[
ist auch eine eingebaute Bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Aber Sie sind nicht weit weg -[
odertest
müssen ein externer Befehl sein. In den Tagen des ursprünglichen Bourne war die Shell[
tatsächlich ein externer Befehl und existiert heute noch,/usr/bin/[
da POSIX einen externen Befehl benötigt. Pubs.opengroup.org/onlinepubs/009695399/utilities/test.html POSIX benötigt nur sehr wenige eingebaut sein pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Eingebaut[
ist für Effizienzksh
; benutze einen Hashbang oder-s ksh
. Übrigens haben ksh und bash[[
"eingebaut", aber es ist ein Schlüsselwort , im Gegensatz zu[
einer eingebauten Shell . (ksh :whence -v [ [[
; bashtype [ [[
:) Builtins und externe Befehle sind syntaktisch gleich. Ein Weg, der sich davon[[
unterscheidet,[
besteht darin, dass[[
einige Erweiterungen in seinen Argumenten unterdrückt werden, die als eingebautes Element nicht möglich waren - ebenso wenig wie eine{
Gruppierung, wenn es ein eingebautes Element wäre. Dies kann der Grund sein, warum{x
(oder[[x
) es sich seltsam anfühlt, ein Token zu sein. Ich denke, es ist richtig zu sagen, dass Builtins und Keywords lexikalisch, aber nicht syntaktisch ähnlich sind. @SergiyKolodyazhnyy[[
kann ein externer Befehl sein! Das heißt, es kann sich um ein Programm handeln und nicht um eine Syntax, die von Ihrer Shell direkt unterstützt wird. Die Unterstützung einer platzlosen Syntax wäre möglichksh
, würde jedoch auf Systemen mit externem System fehlschlagen. Aus[[
Kompatibilitätsgründen ist es daher besser, den erforderlichen Speicherplatz beizubehalten.BusyBox stellt
[[
beispielsweise einen externen Befehl bereit.quelle
Da
[[-e
kann an der Shell-Erweiterung teilnehmen (es kann wie verwendet werdenum alle Dateien beginnend mit einem Buchstaben zwischen aufzulisten
[
unde
einschließend), wäre es ein komplettes Chaos, wenn[
und]
wurden Sonderzeichen nicht in der normalen Leer regierten Wort Spaltung beteiligt.quelle