TL; DR : Warum benötigt die POSIX- {
Klammergruppe Leerzeichen nach dem reservierten Wort, die Unterschale jedoch nicht nach dem reservierten Wort (
?
Die POSIX-Shell-Grammatik definiert Klammergruppe und Subshell wie folgt
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
Wenn wir das wörtlich lesen, sind Leerzeichen von Bedeutung. Dies würde bedeuten, dass es einen Raum geben muss, der die öffnende und schließende Klammer und Klammer wie in beschreibt
{ echo hello world; }
( echo hello world )
Dies würde auch mit den Definitionen des zusammengesetzten Befehls übereinstimmen :
Jeder dieser zusammengesetzten Befehle hat am Anfang ein reserviertes Wort oder einen Steueroperator und am Ende ein entsprechendes reserviertes Terminatorwort oder einen Operator.
Was jedoch keinen Sinn ergibt, ist, warum (list)
und ( list )
funktioniert einwandfrei (dieser Platz danach (
ist nicht erforderlich), jedoch muss die Klammererweiterung einen führenden Platz haben, dh {echo hello;}
würde nicht funktionieren.
Natürlich wäre es sinnvoll, ein reserviertes Wort, das als Shell-Wort behandelt wird, danach ein Leerzeichen zu benötigen, um mit dem Konzept der Feldaufteilung übereinzustimmen . Die Definition selbst erwähnt jedoch keine Leerzeichen. Wenn darüber hinaus {
und (
sind beide als reservierte Wörter von POSIX Definition der Verbindung Befehl, warum sie anders in Bezug auf die Raumzeichen nach diesen reservierten Wörter behandelt werden? Im Handbuch zu ksh (1) heißt es nun:
Wörter, bei denen es sich um Zeichenfolgen handelt, werden durch nicht zitierte Leerzeichen (Leerzeichen, Tabulator und Zeilenumbruch) oder Metazeichen (<,>, |,;, &, (und)) begrenzt.
Mit anderen Worten ist es sinnvoll, dass ksh (
als Wortbegrenzer erkennt , wobei das erste Wort ein Befehl oder eine Variablenzuweisung ist. POSIX scheint jedoch nicht (
als Meta-Zeichen zu erwähnen . Die einzig mögliche Erklärung, die ich für die POSIX-Grammatik gefunden habe, ist, dass sie {
als "Token" betrachtet wird, wobei as (
nicht als eines aufgeführt ist.
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
Was wäre also eine genaue Begründung für diese Diskrepanz?
Akzeptierte Antwort Hinweise:
Das akzeptierte Häkchen wurde in Isaacs Antwort verschoben, da es den Standard selbst enthält, der meine Frage direkt anspricht:
Zum Beispiel sind '(' und ')' Steuerungsoperatoren, so dass
<space>
in (Liste) keine benötigt wird. '{' Und '}' sind jedoch reservierte Wörter in {list;}, so dass in diesem Fall die führenden<space>
und<semicolon>
erforderlich sind.Kusalanandas Antwort annehmen. Kusalanandas Antwort spricht das an, was ich brauchte, allerdings hauptsächlich aus informeller und intuitiver Sicht. es weist darauf hin,{
ist ein reserviertes Wort und(
ist Operator. Michael Homer bemerkte dasselbe auch in den Kommentaren - in der Definition des zusammengesetzten Befehls heißt es (Hervorhebung hinzugefügt):Jeder dieser zusammengesetzten Befehle hat am Anfang ein reserviertes Wort oder einen Steueroperator
{
sind als reserviertes Wort definiert, ähnlichfor
oderwhile
in der Shell-Grammatik aufgeführt (siehe den letzten Codeblock in der Frage).Abschnitt 2.9 besagt (Hervorhebung hinzugefügt):
Insbesondere enthalten die Darstellungen einen Abstand zwischen Token an einigen Stellen, an denen
<blank>
s nicht erforderlich wäre (wenn einer der Token ein Operator ist).Während der Standard nicht explizit
(
als Operator definiert(
wird, wird er als Operator bezeichnet. Insbesondere Abschnitt 2.9.2 sagtWenn die Pipeline mit dem reservierten Wort beginnt! und Befehl1 ist ein Unterschalenbefehl. Die Anwendung muss sicherstellen, dass der Operator (am Anfang von Befehl1 durch ein oder mehrere Zeichen vom! getrennt ist. Das Verhalten des reservierten Wortes! unmittelbar gefolgt vom Operator (ist nicht angegeben.
Die Frage zum Stapelüberlauf durch digitales Trauma weist auf Abschnitt 2.4 zu reservierten Wörtern hin:
Diese Erkennung erfolgt nur, wenn keines der Zeichen in Anführungszeichen steht und wenn das Wort wie folgt verwendet wird:
-Das erste Wort eines Befehls
Wie in Kusalanandas Antwort erwähnt: "Die in der POSIX-Grammatik angezeigten Leerzeichen sind keine Leerzeichen, die in den Shell-Eingabedaten vorhanden sein müssen, sondern nur eine Möglichkeit, die Grammatik selbst anzuzeigen. Die Tatsache, dass die geschweiften Klammern reservierte Wörter sind, impliziert dies Sie müssen von Leerzeichen umgeben sein. "Wie von Michael Homer in den Kommentaren erwähnt:" Wenn die Leerzeichen für sich genommen bedeutsam wären, müssten sie in der Produktion aufgeführt werden. "
Fall abgeschlossen.
{
und (
werden beide nach der POSIX-Definition des zusammengesetzten Befehls als reservierte Wörter betrachtet", vgl. "Jeder dieser zusammengesetzten Befehle hat am Anfang ein reserviertes Wort oder einen Steueroperator ".
' '
) enthalten müssen. Stattdessen werden die Leerzeichen durch die Wörter impliziert, die Wörter sind.
command : simple_command | compound_command | compound_command redirect_list | function_definition ;
ist eine Produktion , die sagt , wo Sie einen Befehl haben, kann es mit Umleitung oder eine Funktionsdefinition ein einfacher Befehl, Verbindung einen Befehl oder eine Verbindung Befehl sein.