Differences between revisions 19 and 37 (spanning 18 versions)
Revision 19 as of 2010-11-04 08:39:36
Size: 2077
Editor: finproxy
Comment: Fix typo in word POSIX
Revision 37 as of 2025-05-26 12:16:02
Size: 3410
Editor: 81
Comment: (Code): adjust comment lines to phone display width
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
For several reasons: The {{{`cmd`}}} backtick format is the legacy syntax for [[CommandSubstitution|command substitution]], required only by more than 30-year-old [[BourneShell|Bourne shells]]. The modern POSIX {{{$(...)}}} syntax is preferred for many reasons:
Line 5: Line 5:
 * It's easier to read. The character {{{`}}} is difficult to read with small or unusual fonts. === Important differences ===
 * Backslashes (\) inside backticks are handled in a non-obvious manner:
{{{#!highlight bash
# shopt: revert to
# non-standard mode where
# echo '\a' outputs \a
# instead ofa BEL character
Line 7: Line 13:
 * It's easier to type. The physical key to produce the character may be located in an obscure place on keyboards, or may not be present at all (like in the standard italian keyboard). $ shopt -u xpg_echo
$ echo "`echo \\a`"
a
Line 9: Line 17:
 * The backtick is easily confused with a single quote. People who see {{{$()}}} don't normally press the wrong keys. On the other hand, some people who see {{{`cmd`}}} may mangle it into {{{'cmd'}}} because they don't know what a backtick is.
 * It makes nesting command substitutions easier. Compare:
  {{{
  x=$(grep $(dirname "$path") file)
  x=`grep \`dirname "$path"\` file`}}}
 It just gets uglier and uglier after two levels.
$ echo "`echo \\\\a`"
\a
Line 16: Line 20:
 * Backslashes (\) inside backticks are handled in a non-obvious manner:
  {{{
  
$ echo "`echo \\a`" "$(echo \\a)"
  a \a
  $ echo "`echo \\\\a`" "$(echo \\\\a)"
  \a
\\a
  # Note that this is true for *single quotes* too!
  $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar" 
  foo is \, bar is \\
  }}}
$ echo "$(echo \\a)"
\\a

# Note that this is true
#
for *single quotes* too!

$ str=`echo '\\'`
$
echo "str is $str"
str is \

$ st
r=$(echo '\\')
$
echo "str is $str"
str is \\
}}}
Line 28: Line 36:
  {{{
  echo "x is $(echo "$y" | sed ...)"}}}
 {{{#!highlight bash
echo "$(sed ... <<<"$y")"
}}}
Line 31: Line 40:
  {{{
  echo "x is `echo \"$y\" | sed ...`"}}}
 {{{#!highlight bash
echo "`sed ... <<<\"$y\"`"
}}}
Line 35: Line 45:
The only time backticks are preferred is when writing code for the oldest Bourne shells, which are not POSIX compliant. See [[http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03|POSIX standard and section "2.6.3 Command Substitution"]] for {{{$()}}}.  * It makes nesting command substitutions easier. Compare:
 {{{#!highlight bash
x=$(basename "$(pwd)")
x=`basename "\`pwd\`"`
}}}
 It just gets uglier and uglier after two levels. {{{$()}}} forces an entirely new context for quoting, so that everything within the command substitution is protected and can be treated as though it were on its own, with no special concern over quoting and escaping.

=== Other advantages ===
 * The function of {{{$(...)}}} as being an expansion is visually clear. The syntax of a {{{$}}}-prefixed token is consistent with all other expansions that are parsed from within double-quotes, at the same time, from left-to-right. Backticks are the only exception. This improves human and machine readability, and consistent syntax makes the language more intuitive for readers.

 * Per the above, people are (hopefully) accustomed to seeing double-quoted expansions and substitutions with the usual {{{"$..."}}} syntax. Quoting command substitutions is almost always the correct thing to do, yet the great majority of {{{`...`}}} specimens we find in the wild are left unquoted, perhaps because those who still use the legacy syntax are less experienced, or they don't associate it with the other expansions due to the different syntax. In addition, the {{{`}}} character is easily camouflaged when adjacent to {{{"}}} making it even more difficult to read, especially with small or unusual fonts.

 * The backtick is also easily confused with a single quote.

=== See also: ===
 * [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03|POSIX standard section "2.6.3 Command Substitution"]]
 * [[http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html#tag_23_02_06_03|POSIX rationale for including ksh's $() syntax]]
 * [[https://web.archive.org/web/20230318045013/http://wiki.bash-hackers.org/syntax/expansion/cmdsubst|bash-hackers: command substitution]]

Why is $(...) preferred over `...` (backticks)?

The `cmd` backtick format is the legacy syntax for command substitution, required only by more than 30-year-old Bourne shells. The modern POSIX $(...) syntax is preferred for many reasons:

Important differences

  • Backslashes (\) inside backticks are handled in a non-obvious manner:

   1 # shopt: revert to
   2 # non-standard mode where
   3 # echo '\a' outputs \a
   4 # instead ofa BEL character
   5 
   6 $ shopt -u xpg_echo
   7 $ echo "`echo \\a`"
   8 a
   9 
  10 $ echo "`echo \\\\a`"
  11 \a
  12 
  13 $ echo "$(echo \\a)"
  14 \\a
  15 
  16 # Note that this is true
  17 # for *single quotes* too!
  18 
  19 $ str=`echo '\\'`
  20 $ echo "str is $str"
  21 str is \
  22 
  23 $ str=$(echo '\\')
  24 $ echo "str is $str"
  25 str is \\
  • Nested quoting inside $() is far more convenient.

       1 echo "$(sed ... <<<"$y")"
    

    In this example, the quotes around $y are treated as a pair, because they are inside $(). This is confusing at first glance, because most C programmers would expect the quote before x and the quote before $y to be treated as a pair; but that isn't correct in shells. On the other hand,

       1 echo "`sed ... <<<\"$y\"`"
    
    requires backslashes around the internal quotes in order to be portable. Bourne and Korn shells require these backslashes, while Bash and dash don't.
  • It makes nesting command substitutions easier. Compare:
       1 x=$(basename "$(pwd)")
       2 x=`basename "\`pwd\`"`
    

    It just gets uglier and uglier after two levels. $() forces an entirely new context for quoting, so that everything within the command substitution is protected and can be treated as though it were on its own, with no special concern over quoting and escaping.

Other advantages

  • The function of $(...) as being an expansion is visually clear. The syntax of a $-prefixed token is consistent with all other expansions that are parsed from within double-quotes, at the same time, from left-to-right. Backticks are the only exception. This improves human and machine readability, and consistent syntax makes the language more intuitive for readers.

  • Per the above, people are (hopefully) accustomed to seeing double-quoted expansions and substitutions with the usual "$..." syntax. Quoting command substitutions is almost always the correct thing to do, yet the great majority of `...` specimens we find in the wild are left unquoted, perhaps because those who still use the legacy syntax are less experienced, or they don't associate it with the other expansions due to the different syntax. In addition, the ` character is easily camouflaged when adjacent to " making it even more difficult to read, especially with small or unusual fonts.

  • The backtick is also easily confused with a single quote.

See also:

BashFAQ/082 (last edited 2025-05-26 12:16:02 by 81)