TL; DR : Por que o grupo de chaves POSIX precisa de espaços após a {
palavra reservada, mas o subshell não após a palavra reservada (
?
A gramática de shell POSIX define o grupo de chaves e o subshell da seguinte maneira
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
Agora, se estamos lendo isso literalmente, os espaços são significativos. Isso significa que deve haver espaço delineando a chave de abertura e fechamento e o parêntese, como
{ echo hello world; }
( echo hello world )
Isso também se alinharia às definições de comando composto :
Cada um desses comandos compostos possui uma palavra reservada ou operador de controle no início e uma palavra ou operador reservado terminador correspondente no final.
No entanto, o que não faz sentido é o porquê (list)
e ( list )
funciona muito bem (esse espaço depois (
não é necessário), no entanto, a expansão da cinta precisa ter um espaço à frente, ou seja {echo hello;}
, não funcionaria.
É claro que a palavra reservada sendo tratada como palavra shell faria sentido precisar de um espaço depois para se alinhar com o conceito de divisão de campos , no entanto, a própria definição não faz menção de espaços. Além disso, se {
e (
são consideradas palavras reservadas pela definição POSIX de comando composto, por que são tratadas de maneira diferente em relação ao caractere de espaço após essas palavras reservadas? Agora, o manual do ksh (1) declara:
As palavras, que são seqüências de caracteres, são delimitadas por caracteres de espaço em branco sem aspas (espaço, tabulação e nova linha) ou metacaracteres (<,>, |,;, &, (e))
Em outras palavras, faz sentido que o ksh reconheça (
como delimitador de palavras, onde a primeira palavra seria um comando ou atribuição de variável. POSIX, no entanto, não parece ser mencionado (
como meta-caractere. A única explicação possível que encontrei no que diz respeito à gramática POSIX é que ela {
é considerada um "token", onde (
não está listado como um.
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
Então, qual seria o raciocínio preciso para essa discrepância?
Notas de respostas aceitas:
Movi a marca de seleção aceita para a resposta de Isaac, pois fornece ao formulário o padrão em si que aborda diretamente minha pergunta:
Por exemplo, '(' e ')' são operadores de controle, de modo que não
<space>
é necessário em (lista). No entanto, '{' e '}' são palavras reservadas em {list;}, portanto, neste caso, as iniciais<space>
e<semicolon>
são obrigatórias.Aceitando a resposta de Kusalananda. A resposta de Kusalananda aborda o que eu precisava, embora principalmente do ponto de vista informal e intuitivo; indica que{
é uma palavra reservada e(
é operador. Michael Homer também observou o mesmo nos comentários - que a definição do Comando Composto afirma (ênfase adicionada):Cada um desses comandos compostos possui uma palavra reservada ou operador de controle no início
{
são definidos como palavras reservadas, semelhantesfor
ouwhile
listadas na Shell Grammar (consulte o último bloco de código na pergunta)A Seção 2.9 declara (grifo nosso):
Em particular, as representações incluem espaçamento entre tokens em alguns lugares onde
<blank>
s não seria necessário (quando um dos tokens é um operador).Enquanto o padrão não define explicitamente
(
como operador,(
é referido como operador; especificamente, a seção 2.9.2 dizSe o pipeline começar com a palavra reservada! e command1 é um comando subshell, o aplicativo deve garantir que o operador (no início do comando1 seja separado do! por um ou mais caracteres. O comportamento da palavra reservada! imediatamente seguido pelo operador (não é especificado.
Pergunta sobre Stack Overflow by Digital Trauma indica a Seção 2.4 em Palavras reservadas:
Este reconhecimento deve ocorrer apenas quando nenhum dos caracteres é citado e quando a palavra é usada como:
-A primeira palavra de um comando
Como mencionado na resposta de Kusalananda "Os espaços mostrados na gramática POSIX não são espaços que precisam estar nos dados de entrada do shell, mas apenas uma maneira de exibir a gramática em si. É o fato de que os aparelhos são palavras reservadas que implica que eles precisam ser cercados por espaços em branco "Como mencionado por Michael Homer nos comentários:" Se os espaços fossem significativos por si mesmos, eles precisariam ser listados na produção "
Caso encerrado.
{
e(
são considerados palavras reservadas pela definição POSIX de comando composto", cf. "Cada um desses comandos compostos possui uma palavra reservada ou operador de controle no início".' '
). Em vez disso, os espaços estão implícitos em quais símbolos são palavras.command : simple_command | compound_command | compound_command redirect_list | function_definition ;
é uma produção que diz onde você pode ter um comando, pode ser um comando simples, comando composto ou comando composto com redirecionamento ou definição de função.Respostas:
Essa é uma limitação da maneira como o shell quebra linhas em tokens.
O shell lê as linhas do arquivo de entrada e, de acordo com a seção 2 "Introdução ao Shell", as converte em uma palavra ou em um operador :
{é uma palavra reservada
Algumas palavras são palavras reservadas
As palavras, para serem reconhecidas como palavras, devem ser delimitadas .
Principalmente por espaços em branco (ponto 7) e pelos operadores.
(é um operador
Os operadores se destacam :
Onde "operadores" são :
Os operadores de redirecionamento são :
Os operadores de controle são :
Conclusão
Portanto, '(' e ')' são operadores de controle, enquanto '{' '}' são palavras reservadas.
E a mesma descrição exata da sua pergunta está dentro da especificação :
O que explica exatamente por que um espaço (ou outro delimitador) é necessário após a
{
.Isso é válido:
Como é isso:
Este:
Ou até isso:
fonte
A diferença entre as chaves e os parênteses são de que as chaves (e
!
) são palavras reservadas, assim comofor
,if
,then
etc., enquanto parênteses são operadores de controle. As palavras precisam ser separadas por espaços em branco.Isso significa que, assim como você não pode ter
você não pode ter
ou
Os espaços mostrados na gramática POSIX não são espaços que precisam estar presentes nos dados de entrada do shell, mas apenas uma maneira de exibir a própria gramática. É o fato de os chavetas serem palavras reservadas que implica que elas precisam ser cercadas por espaços em branco, enquanto os parênteses de um subshell não.
fonte
(
como operador? Não é na seção de gramática, pelo menos;
. Obrigado por isso.()
operadores de controle como os|
que envolvem subcascas. E{ }
funciona no shell atual e não pode envolver um subshell.(
operador