Bourne | Ash |  #!  | find | ARG_MAX | Shells | whatshell | portability | permissions | UUOC | ancient | - | ../Various | HOME
"$@" | echo/printf | set -e | test | tty defs | tty chars | $() vs ) | IFS | using siginfo | nanosleep | line charset | locale


"$( )" command substitution vs. embedded ")"

This page doesn't serve any purpose but fun, it's just about a special point concerning the robustness of shell parsers.

2016-04-17 (see recent changes)

In some shells, $( ) collides with other, "unbalanced", yet valid, right parentheses.
And there are some more subtle issues.

The much more famous issue, $( ) vs. `...`, is mentioned in the additional end notes.

What does the standard say?

The SUSv3 rationale and SUSv4 rationale to shell commands, C.2.9, about "case x in (x)" embedded in "$( )":

"An optional left parenthesis before pattern was added to allow numerous historical KornShell scripts to conform.
At one time, using the leading parenthesis was required if the case statement was to be embedded within a "$()"
command substitution; this is no longer the case with the POSIX shell. Nevertheless, many historical scripts use
the left parenthesis, if only because it makes matching-parenthesis searching easier in vi and other editors."

However, there are some cornercases for "$( )" even in shells which try to implement posix.

The following table lists the results for some testcases. These tests exploit the case command and here-documents.
They were taken from the above URL or Usenet and the thread <mailman.20673.1135786095.20277.bug-bash@gnu.org>
in gnu.bash.bug (Dan Jacobson and Eric Blake). Jilles Tjoelker pointed out the problem with '# \'.
The table below unfortunately suggested wrong behaviour as correct for test D.2 until Robert Elz kindly pointed out that it should fail.

Examples, each to be embedded in $( ) , see full testcases

A.1      "case x in x)"
A.2 "case x in x)" with a comment
A.3 "case x in (x)"
A.4 "case x in (x)" with a comment
A.5 "case x in (x)" with \n and without ";;" before "esac"
B ) in quotes
C ) after a comment sign
D.1 ) embedded in a here-document
D.2 ) embedded in a here-document, with \() inside
D.3 ) embedded in a here-document, eof and closing ) on same line According to POSIX/SUSv1-v4 it should fail with unterminated here-doc (see 2.7.4).
D.4 eof and closing ) on same line, combined with another correct terminator
E ) as delimiter for an embedded here-document (academic)
F unbalanced quote in an embedded here-document
G \ at end of line
H empty
Shell  A.1   A.2   A.3   A.4   A.5    B     C     D.1     D.2     D.3     D.4     E     F     G     H  

ash (original release) + + - - - + + + + + - + + + -
ash (early variants) + + - - - + + + + + - + + + +
ash (BSD/OS, NetBSD, FreeBSD, dash, slackware, busybox, Minix) + + + + + + + + + + - + + + +
bash-1.14.7/2.05/3.0 - - + + + + - - - + - - - + +
bash-3.1.0 - - + + + + - - - + - - - - +
bash-3.2.0 - - + + + + + - - + - - - - +
bash-4.0.10 + + + + - + + + + + - + + - +
bash-4.0.18/-4.0.35 + + + + + + + + - + - + + - +
bash-4.1.0/-4.1.7 + + + + + + + + + uw - + + - +
bash-4.2.0 + + + + + + + + + uw - + + + +
bosh-2016-02-02 + + + + + + + + + + - + + + +
ksh86 - - - - - + - - - + - - - + +
ksh88-a / e / i / i(SunOS xpg4/posix variant) - - + + + + - - _ + - - - + +
ksh93-d + + + + + + + + + + - + + - +
ksh93-k / t + + + + + + + + + + - + + + +
pdksh-5.2.14 - - + + + + - - - + - - - + +
posh-0.5.4/0.6.17 - - + + + + - - - + - - - + +
mksh-R28/R39 - - + + + + - - - + - - - + +
mksh-R52b + + + + + + + + + u - + + + +
zsh-3.0.0/4.3.9 - - + + + + - - - + - - - + +

("-" means a parsing failure, "+" means output as expected, "u" means unexpected output (wrong according to POSIX, but probably depending on the shell documentation), "w" means a warning)

Additional Notes:


<http://www.in-ulm.de/~mascheck/various/cmd-subst/>