Discussion:
[Help-bash] Separation of compound commands
D630
2017-03-14 16:24:17 UTC
Permalink
Why does A work, but B doesn't?

# A
{ { :; } }
if :; then if :; then :; fi fi
{ (:) }

# B
{ (()) }
{ [[ 1 ]] }
Nicholas Chambers
2017-03-14 16:42:16 UTC
Permalink
Post by D630
Why does A work, but B doesn't?
# A
{ { :; } }
if :; then if :; then :; fi fi
{ (:) }
Braces can be nested, however statements/commands need to be terminated.
That is why the first works. I am not sure what part you don't
understand in the second example. For the third, bash can tell that the
statement : is over since it is wrapped in ()'s. If it didn't have those
you would need a semicolon again (ie { :; }).
Post by D630
# B
{ (()) }
{ [[ 1 ]] }
(()) is a very different kind of statement than (:). (()) is for math. {
(()); } works. { ( (()) ) } works. { (( 3 + 4 )); } works. Same with [[
1 ]]. It is a statement, so it needs some kind of delimiter for bash to
say its finished. Again, { ( [[ 1 ]] ) } works, and { [[ 1 ]]; } works.
--
Nicholas Chambers
Technical Support Specialist
***@lightspeedsystems.com
1.800.444.9267
www.lightspeedsystems.com
Andy Chu
2017-03-14 17:28:08 UTC
Permalink
Yes, the statements in (A) are strictly POSIX -- { } and (). As far as I
can tell, the lack of semi-colons follows from the POSIX grammar:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10

(B) are bash extensions, I think borrowed from ksh. However I think
there's no reason that shouldn't work if [[ and (( are parsed in the same
place as if/for/etc.

I tested my OSH parser and they both work fine.

$ bin/osh --ast-output - -c '{ [[ 1 ]] }'
(BraceGroup children:[(DBracket expr:(WordTest w:{(1)}))] spids:[0])

$ bin/osh --ast-output - -c '{ (( 1 )) }'
(BraceGroup children:[(DParen child:(ArithWord w:{(Lit_Digits 1)}))]
spids:[0])

(Although (()) doesn't work, (( 1 )) works. I didn't really think about
it, but (( )) has to be non-empty in my parser.)

Andy




On Tue, Mar 14, 2017 at 9:42 AM, Nicholas Chambers <
Post by Nicholas Chambers
Post by D630
Why does A work, but B doesn't?
# A
{ { :; } }
if :; then if :; then :; fi fi
{ (:) }
Braces can be nested, however statements/commands need to be terminated.
That is why the first works. I am not sure what part you don't understand
in the second example. For the third, bash can tell that the statement : is
over since it is wrapped in ()'s. If it didn't have those you would need a
semicolon again (ie { :; }).
Post by D630
# B
{ (()) }
{ [[ 1 ]] }
(()) is a very different kind of statement than (:). (()) is for math. {
(()); } works. { ( (()) ) } works. { (( 3 + 4 )); } works. Same with [[ 1
]]. It is a statement, so it needs some kind of delimiter for bash to say
its finished. Again, { ( [[ 1 ]] ) } works, and { [[ 1 ]]; } works.
--
Nicholas Chambers
Technical Support Specialist
1.800.444.9267
www.lightspeedsystems.com
Chet Ramey
2017-03-14 19:47:15 UTC
Permalink
Post by D630
Why does A work, but B doesn't?
# A
{ { :; } }
if :; then if :; then :; fi fi
{ (:) }
# B
{ (()) }
{ [[ 1 ]] }
The stuff between the braces has to be a compound_list. A compound_list
needs a terminator (`&', `;', `\n', etc.). The (( and [[ commands aren't
specified as being terminated by operators in the bash grammar; they're
more like commands that begin and end with reserved words. When you read
a reserved word like ]] or )), you are not in a position to read another
reserved word (`}' is a reserved word, not an operator), so you need a
separator, which in this case is the list terminator.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://cnswww.cns.cwru.edu/~chet/
Loading...