TL;DR: Why does POSIX brace group need spaces after {
reserved word but subshell doesn't after reserved word (
?
POSIX shell grammar defines brace group and subshell as follows
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
Now, if we're reading that literally, spaces are significant. This would mean that there has to be space delineating opening and closing brace and parenthesis as in
{ echo hello world; }
( echo hello world )
This would also align with Compound Command definitions:
Each of these compound commands has a reserved word or control operator at the beginning, and a corresponding terminator reserved word or operator at the end.
However what doesn't make sense is why (list)
and ( list )
work just fine (that space after (
is not required), however brace expansion has to have a leading space, i.e. {echo hello;}
wouldn't work.
Of course reserved word being treated as shell word would make sense needing a space afterwards to align with concept of field splitting, however definition itself makes no mention of spaces. Further, if {
and (
are both considered reserved words by POSIX definition of compound command, why they're treated differently in regards to space character after these reserved words? Now, ksh(1) manual does state:
Words, which are sequences of characters, are delimited by unquoted white-space characters (space, tab and newline) or meta-characters (<, >, |, ;, &, ( and ))
In other words, it makes sense that ksh would recognize (
as word delimiter, where first word would be a command or variable assignment. POSIX, however doesn't appear to mention (
as meta-character. The only possible explanation I found as far as POSIX grammar goes is that {
is considered a "token", where as (
is not listed as one.
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
So what would be precise reasoning for this discrepancy ?
Accepted Answer Notes:
Moved accepted checkmark to Isaac's answer since it provides quote form the standard itself which directly addresses my question:
For instance, '(' and ')' are control operators, so that no
<space>
is needed in (list). However, '{' and '}' are reserved words in { list;}, so that in this case the leading<space>
and<semicolon>
are required.Accepting Kusalananda's answer. Kusalananda's answer addresses what I needed, though mostly from informal and intuitive point of view; it points out{
is a reserved word and(
is operator. Michael Homer also noted the same in the comments - that Compound Command definition states(emphasis added):Each of these compound commands has a reserved word or control operator at the beginning
{
are defined as reserved word, similar tofor
orwhile
, listed in Shell Grammar (see the last code block in the question)Section 2.9 states(emphasis added):
In particular, the representations include spacing between tokens in some places where
<blank>
s would not be necessary (when one of the tokens is an operator).While the standard doesn't explicitly define
(
as an operator,(
is referred to as operator; specifically, section 2.9.2 saysIf the pipeline begins with the reserved word ! and command1 is a subshell command, the application shall ensure that the ( operator at the beginning of command1 is separated from the ! by one or more characters. The behavior of the reserved word ! immediately followed by the ( operator is unspecified.
Question on Stack Overflow by Digital Trauma points out Section 2.4 on Reserved Words:
This recognition shall only occur when none of the characters is quoted and when the word is used as:
-The first word of a command
As mentioned in Kusalananda's answer "The spaces shown in the POSIX grammar are not spaces that needs to be there in the shell input data, but just a way of displaying the grammar itself. It is the fact that the braces are reserved words that implies that they have to be surrounded by whitespace" As mentioned by Michael Homer in the comments:"If the spaces were significant in their own right, they'd need to be listed in the production"
Case closed.
{
and(
are both considered reserved words by POSIX definition of compound command" cf. "Each of these compound commands has a reserved word or control operator at the beginning".' '
). Instead, the spaces are implied by what tokens are words.command : simple_command | compound_command | compound_command redirect_list | function_definition ;
is a production which says where you can have a command, it can be one of simple command, compound command, or compound command with redirection, or a function definition.