ARG_MAX
| Shells
| portability
| permissions
| UUOC
| ancient
| -
| ../Various
| HOME
$() 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.
The
SUSv3 rationale to shell commands, C.2.9, about
"case x in (x)" embedded in "$( )":
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 '# \'.
| 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 | - | - | + | + | + | + | - | - | - | - | + | + |
case
command yet.
In fact, the ash parser doesn't need this workaround. However, this is also an issue of script portability.
$( )" yet and thus had not implemented the opening paren in a case pattern, yet.
$( )" vs. `...`:
Without doubt, the "$( )" syntax is the cleaner design because there are no escaping
rules to consider.
An often mentioned advantage of the "$( )" syntax:
it allows clean nesting for this reason. However, if you really have
to nest command substitution, then you should split into separate commands,
to ease maintencance and to improve readability. A better
argument: backquotes are easily confused with apostrophes -- not so
much when actually using them (in terminals with fixed width fonts),
but especially in other sources of documentation using arbitrary fonts.
Another better argument: \ is special in `...` so you have to escape twice.
However, the "$( )" syntax is not as traditionally portable
as the `...` form.
...and in ksh88 (at least from release a to i) you have to be aware
of a subtle quoting issue inside $( ).
Single quotes in embedded here-documents are converted to double quotes:
echo $(cat << EOF
"double quotes"
'single quotes'
EOF
)
results in
"double quotes" "single quotes"This happens for the
$( ) form but not for the `` form.