What is the benefit of using $() instead of backticks in shell scripts?

后端 未结 8 979
梦谈多话
梦谈多话 2020-11-22 05:05

There are two ways to capture the output of command line in bash:

  1. Legacy Bourne shell backticks ``:

    var=`command`
             
    
    
            
相关标签:
8条回答
  • 2020-11-22 05:54

    The backticks (`...`) is the legacy syntax required by only the very oldest of non-POSIX-compatible bourne-shells and $(...) is POSIX and more preferred for several reasons:

    • 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 \\
      
    • Nested quoting inside $() is far more convenient:

      echo "x is $(sed ... <<<"$y")"
      

      instead of:

      echo "x is `sed ... <<<\"$y\"`"
      

      or writing something like:

      IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
      

      because $() uses an entirely new context for quoting

      which is not portable as Bourne and Korn shells would require these backslashes, while Bash and dash don't.

    • Syntax for nesting command substitutions is easier:

      x=$(grep "$(dirname "$path")" file)
      

      than:

      x=`grep "\`dirname \"$path\"\`" file`
      

      because $() enforces an entirely new context for quoting, so each command substitution is protected and can be treated on its own without special concern over quoting and escaping. When using backticks, it gets uglier and uglier after two and above levels.

      Few more examples:

      echo `echo `ls``      # INCORRECT
      echo `echo \`ls\``    # CORRECT
      echo $(echo $(ls))    # CORRECT
      
    • It solves a problem of inconsistent behavior when using backquotes:

      • echo '\$x' outputs \$x
      • echo `echo '\$x'` outputs $x
      • echo $(echo '\$x') outputs \$x
    • Backticks syntax has historical restrictions on the contents of the embedded command and cannot handle some valid scripts that include backquotes, while the newer $() form can process any kind of valid embedded script.

      For example, these otherwise valid embedded scripts do not work in the left column, but do work on the rightIEEE:

      echo `                         echo $(
      cat <<\eof                     cat <<\eof
      a here-doc with `              a here-doc with )
      eof                            eof
      `                              )
      
      
      echo `                         echo $(
      echo abc # a comment with `    echo abc # a comment with )
      `                              )
      
      
      echo `                         echo $(
      echo '`'                       echo ')'
      `                              )
      

    Therefore the syntax for $-prefixed command substitution should be the preferred method, because it is visually clear with clean syntax (improves human and machine readability), it is nestable and intuitive, its inner parsing is separate, and it is also more consistent (with all other expansions that are parsed from within double-quotes) where backticks are the only exception and ` character is easily camouflaged when adjacent to " making it even more difficult to read, especially with small or unusual fonts.

    Source: Why is $(...) preferred over `...` (backticks)? at BashFAQ

    See also:

    • POSIX standard section "2.6.3 Command Substitution"
    • POSIX rationale for including the $() syntax
    • Command Substitution
    • bash-hackers: command substitution
    0 讨论(0)
  • 2020-11-22 05:56

    From man bash:

           $(command)
    or
           `command`
    
    Bash performs the expansion by executing command and replacing the com-
    mand  substitution  with  the  standard output of the command, with any
    trailing newlines deleted.  Embedded newlines are not deleted, but they
    may  be  removed during word splitting.  The command substitution $(cat
    file) can be replaced by the equivalent but faster $(< file).
    
    When the old-style backquote form of substitution  is  used,  backslash
    retains  its  literal  meaning except when followed by $, `, or \.  The
    first backquote not preceded by a backslash terminates the command sub-
    stitution.   When using the $(command) form, all characters between the
    parentheses make up the command; none are treated specially.
    
    0 讨论(0)
提交回复
热议问题