TL; DR : ¿Por qué el grupo de llaves POSIX necesita espacios después de la {
palabra reservada pero la subshell no necesita después de la palabra reservada (
?
La gramática del shell POSIX define el grupo de llaves y el subshell de la siguiente manera
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
Ahora, si estamos leyendo eso literalmente, los espacios son significativos. Esto significaría que debe haber un espacio que delimite la llave de apertura y cierre y el paréntesis como en
{ echo hello world; }
( echo hello world )
Esto también se alinearía con las definiciones de Compound Command :
Cada uno de estos comandos compuestos tiene una palabra reservada u operador de control al principio, y una palabra u operador reservado terminador correspondiente al final.
Sin embargo, lo que no tiene sentido es por qué (list)
y ( list )
funciona bien (ese espacio después (
no es necesario), sin embargo, la expansión de llaves debe tener un espacio principal, es decir {echo hello;}
, no funcionaría.
Por supuesto, la palabra reservada que se trata como palabra shell tendría sentido necesitar un espacio para alinearse con el concepto de división de campo , sin embargo, la definición en sí misma no menciona los espacios. Además, si {
y (
son dos palabras reservadas considerado por POSIX definición de orden compuesta, ¿por qué se les trata de manera diferente en lo que respecta al carácter de espacio después de estas palabras reservadas? Ahora, el manual ksh (1) dice:
Las palabras, que son secuencias de caracteres, están delimitadas por espacios en blanco sin comillas (espacio, tabulación y nueva línea) o metacaracteres (<,>, |,;, &, (y))
En otras palabras, tiene sentido que ksh reconozca (
como delimitador de palabras, donde la primera palabra sería un comando o una asignación variable. POSIX, sin embargo, no parece mencionarlo (
como meta-personaje. La única explicación posible que encontré en lo que respecta a la gramática POSIX es que {
se considera un "token", donde (
no figura como uno.
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
Entonces, ¿cuál sería un razonamiento preciso para esta discrepancia?
Notas de respuesta aceptadas:
Moved aceptó la marca de verificación a la respuesta de Isaac, ya que proporciona q uote forma el estándar en sí que aborda directamente mi pregunta:
Por ejemplo, '(' y ')' son operadores de control, por lo que no
<space>
se necesita ninguno en (lista). Sin embargo, '{' y '}' son palabras reservadas en {list;}, por lo que, en este caso, son las iniciales<space>
y<semicolon>
son obligatorias.Aceptando la respuesta de Kusalananda. La respuesta de Kusalananda aborda lo que necesitaba, aunque principalmente desde un punto de vista informal e intuitivo; señala que{
es una palabra reservada y(
es operador. Michael Homer también notó lo mismo en los comentarios: la definición del Comando Compuesto establece (énfasis agregado):Cada uno de estos comandos compuestos tiene una palabra reservada o un operador de control al principio
{
se definen como palabras reservadas, similaresfor
owhile
enumeradas en la gramática de Shell (consulte el último bloque de código en la pregunta)La sección 2.9 establece (énfasis agregado):
En particular, las representaciones incluyen el espacio entre tokens en algunos lugares donde
<blank>
s no sería necesario (cuando uno de los tokens es un operador).Si bien el estándar no se define explícitamente
(
como un operador,(
se conoce como operador; específicamente, la sección 2.9.2 diceSi la tubería comienza con la palabra reservada! y command1 es un comando subshell, la aplicación se asegurará de que el operador (al comienzo del comando1 esté separado del! por uno o más caracteres. El comportamiento de la palabra reservada! inmediatamente seguido por el operador (no está especificado.
La pregunta sobre desbordamiento de pila por trauma digital señala la sección 2.4 sobre palabras reservadas:
Este reconocimiento solo ocurrirá cuando no se cite ninguno de los caracteres y cuando la palabra se use como:
-La primera palabra de un comando
Como se menciona en la respuesta de Kusalananda "Los espacios que se muestran en la gramática POSIX no son espacios que deben estar allí en los datos de entrada del shell, sino solo una forma de mostrar la gramática en sí. Es el hecho de que los corchetes son palabras reservadas que implica que tienen que estar rodeados de espacios en blanco "Como mencionó Michael Homer en los comentarios:" Si los espacios fueran significativos por derecho propio, tendrían que estar incluidos en la producción "
Caso cerrado.
{
y(
son dos palabras reservadas considerado por POSIX definición de orden compuesta" cf. "Cada uno de estos comandos compuestos tiene una palabra reservada o un operador de control al principio".' '
). En cambio, los espacios están implicados por qué tokens son palabras.command : simple_command | compound_command | compound_command redirect_list | function_definition ;
es una producción que dice dónde puede tener un comando, puede ser un comando simple, un comando compuesto o un comando compuesto con redirección, o una definición de función.Respuestas:
Esa es una limitación de la forma en que el shell divide las líneas en tokens.
El shell lee líneas del archivo de entrada y, según la sección 2, "Introducción al shell", las convierte en una palabra o en un operador :
{es una palabra reservada
Algunas palabras son palabras reservadas
Las palabras, para ser reconocidas como palabras, deben delimitarse .
Principalmente por espacios en blanco (punto 7) y por operadores.
(es un operador
Los operadores se mantienen solos :
Donde "operadores" son :
Los operadores de redireccionamiento son :
Los operadores de control son :
Conclusión
Entonces, '(' y ')' son operadores de control, mientras que '{' '}' son palabras reservadas.
Y la misma descripción exacta de su pregunta está dentro de la especificación :
Lo que explica exactamente por qué se requiere un espacio (o algún otro delimitador) después de a
{
.Esto es valido:
Como es esto:
Esta:
O incluso esto:
fuente
La diferencia entre las llaves y los paréntesis son que los apoyos (y
!
) son palabras reservadas, al igual quefor
,if
,then
etc, mientras que entre paréntesis son los operadores de control. Las palabras deben estar separadas por espacios en blanco.Esto significa que al igual que no puedes tener
no puedes tener
o
Los espacios que se muestran en la gramática POSIX no son espacios que deben estar allí en los datos de entrada del shell, sino solo una forma de mostrar la gramática en sí. Es el hecho de que los corchetes son palabras reservadas lo que implica que tienen que estar rodeados de espacios en blanco, mientras que los paréntesis de un subshell no.
fuente
(
como operador? No está en la sección de gramática al menos;
. Gracias por eso.()
como operadores de control, ya|
que ambos implican subcapas. Y{ }
funciona en el shell actual y no puede involucrar un subshell.(
operador