TL; DR : Perché il gruppo di parentesi graffe POSIX ha bisogno di spazi dopo la {
parola riservata, ma la subshell non segue la parola riservata (
?
La grammatica della shell POSIX definisce il gruppo di controventi e la subshell come segue
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
Ora, se lo stiamo leggendo letteralmente, gli spazi sono significativi. Ciò significherebbe che deve esserci spazio che delinea l'apertura e la chiusura di parentesi graffe e parentesi come in
{ echo hello world; }
( echo hello world )
Ciò si allinea anche con le definizioni del comando composto :
Ognuno di questi comandi composti ha una parola riservata o un operatore di controllo all'inizio e una parola riservata o un operatore terminatore corrispondente alla fine.
Tuttavia, ciò che non ha senso è perché (list)
e ( list )
lavorare bene (quello spazio dopo (
non è necessario), tuttavia l'espansione del rinforzo deve avere uno spazio iniziale, cioè {echo hello;}
non funzionerebbe.
Naturalmente la parola riservata che viene trattata come parola shell avrebbe senso avere bisogno di uno spazio in seguito per allinearsi con il concetto di divisione del campo , tuttavia la definizione stessa non fa menzione di spazi. Inoltre, se {
e (
entrambi sono considerati parole riservate dalla definizione POSIX di comando composto, perché vengono trattati in modo diverso rispetto al carattere dello spazio dopo queste parole riservate? Ora, il manuale di ksh (1) afferma:
Le parole, che sono sequenze di caratteri, sono delimitate da caratteri di spazi bianchi non quotati (spazio, tabulazione e nuova riga) o meta-caratteri (<,>, |,;, &, (e))
In altre parole, ha senso che ksh riconoscesse (
come delimitatore di parole, dove la prima parola sarebbe un comando o un'assegnazione variabile. POSIX, tuttavia, non sembra menzionare (
come meta-personaggio. L'unica spiegazione possibile che ho trovato per quanto riguarda la grammatica POSIX è che {
è considerato un "token", dove (
non è elencato come uno.
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
Quindi quale sarebbe il ragionamento preciso per questa discrepanza?
Note di risposta accettate:
Sposta il segno di spunta accettato nella risposta di Isaac poiché fornisce q uote dallo standard stesso che risponde direttamente alla mia domanda:
Ad esempio, "(" e ")" sono operatori di controllo, quindi non
<space>
è necessario in (elenco). Tuttavia, "{" e "}" sono parole riservate in {list;}, quindi in questo caso il comando iniziale<space>
e<semicolon>
sono obbligatori.Accettare la risposta di Kusalananda. La risposta di Kusalananda si rivolge a ciò di cui avevo bisogno, anche se principalmente dal punto di vista informale e intuitivo; indica{
una parola riservata ed(
è operatore. Anche Michael Homer ha notato lo stesso nei commenti - che la definizione di Comando composto afferma (enfasi aggiunta):Ognuno di questi comandi composti ha una parola riservata o un operatore di controllo all'inizio
{
sono definiti come parole riservate, simili afor
owhile
, elencate in Shell Grammar (vedere l'ultimo blocco di codice nella domanda)La sezione 2.9 afferma (enfasi aggiunta):
In particolare, le rappresentazioni includono la spaziatura tra i token in alcuni punti dove
<blank>
s non sarebbe necessario (quando uno dei token è un operatore).Mentre lo standard non definisce esplicitamente
(
come operatore,(
viene indicato come operatore; in particolare, dice la sezione 2.9.2Se la pipeline inizia con la parola riservata! e command1 è un comando subshell, l'applicazione deve assicurarsi che l'operatore (all'inizio del comando1 sia separato da! da uno o più caratteri. Il comportamento della parola riservata! immediatamente seguito dall'operatore (non è specificato.
La domanda su Stack Overflow di Digital Trauma sottolinea la Sezione 2.4 sulle parole riservate:
Questo riconoscimento deve avvenire solo quando nessuno dei caratteri è citato e quando la parola è usata come:
-La prima parola di un comando
Come menzionato nella risposta di Kusalananda "Gli spazi mostrati nella grammatica POSIX non sono spazi che devono essere presenti nei dati di input della shell, ma solo un modo per visualizzare la grammatica stessa. È il fatto che le parentesi graffe sono parole riservate che implica che devono essere circondati da spazi bianchi "Come menzionato da Michael Homer nei commenti:" Se gli spazi fossero significativi di per sé, avrebbero bisogno di essere elencati nella produzione "
Caso chiuso.
{
e (
sono entrambi considerati parole riservate dalla definizione POSIX del comando composto" cfr. "Ciascuno di questi comandi composti ha una parola riservata o un operatore di controllo all'inizio".
' '
). Invece, gli spazi sono impliciti da ciò che i token sono parole.
command : simple_command | compound_command | compound_command redirect_list | function_definition ;
è una produzione che dice dove puoi avere un comando, può essere uno di comando semplice, comando composto o comando composto con reindirizzamento o una definizione di funzione.