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.

2009-12-26 (see recent changes)

$( ) is comfortable about nesting, but collides with other, "unbalanced", yet valid, closing parentheses in some shells.
Also, some parsers stumble over quotes in here-documents embedded in $( ).

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

What does the standard say?

The SUSv3 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, omitting the leading parentheses is still problematic, even in shells which claim posix conformance. And there are some more cornercases for "$( )". 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 + + + + + + + + + + - +
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/>