Bourne | Ash |  #!  | find | ARG_MAX | Shells | 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.

2010-07-29 (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 '# \'.

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 qoutes
C ) after a comment sign
D ) embedded in a here-document
E ) as delimiter for an embedded here-document (most 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     E     F     G     H  

original ash + + - - - + + + + + + -
early ash 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/35 + + + + + + + + + + - +
ksh86 - - - - - + - - - - + +
ksh88-e / i - - + + + + - - - - + +
ksh93-d + + + + + + + + + + - +
ksh93-k / t + + + + + + + + + + + +
pdksh-5.2.14 - - + + + + - - - - + +
posh-0.5.4 - - + + + + - - - - + +
mksh-R28/R39 - - + + + + - - - - + +
zsh-3.0.0/4.2.5 - - + + + + - - - - + +

("-" means a parsing failure, "+" means output as expected)

Additional Notes:


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