Os backticks (ou seja, 'cmd') em shells * sh foram preteridos?

110

Eu já vi esse comentário várias vezes no Unix & Linux, bem como em outros sites que usam o fraseado "backticks foram preteridos", no que diz respeito a shells como Bash & Zsh.

Esta declaração é verdadeira ou falsa?

    
por slm 28.04.2014 / 16:57

2 respostas

117

Existem dois significados diferentes de "obsoletos".

be deprecated: (chiefly of a software feature) be usable but regarded as obsolete and best avoided, typically due to having been superseded.

—New Oxford American Dictionary

Por essa definição, os backticks são obsoletos.

Deprecated status may also indicate the feature will be removed in the future.

Wikipedia

Por esta definição, os backticks não são descontinuados.

Ainda suportado:

Citando a Especificação de grupo aberto em idiomas de comando do Shell , especificamente na seção "2.6.3 Substituição de Comando", pode ser visto que ambas as formas de substituição de comando, backticks ( '..cmd..' ) ou parens dólar ( $(..cmd..) ) ainda são suportadas na medida em que a especificação vai.

trecho

Command substitution allows the output of a command to be substituted in place of the command name itself. Command substitution shall occur when the command is enclosed as follows:

          $(command)

          or (backquoted version):

          'command'

The shell shall expand the command substitution by executing command in a subshell environment (see Shell Execution Environment) and replacing the command substitution (the text of command plus the enclosing $() or backquotes) with the standard output of the command, removing sequences of one or more <newline> characters at the end of the substitution. Embedded <newline> characters before the end of the output shall not be removed; however, they may be treated as field delimiters and eliminated during field splitting, depending on the value of IFS and quoting that is in effect. If the output contains any null bytes, the behavior is unspecified.

Within the backquoted style of command substitution, <backslash> shall retain its literal meaning, except when followed by: '$', '\'', or <backslash>. The search for the matching backquote shall be satisfied by the first unquoted non-escaped backquote; during this search, if a non-escaped backquote is encountered within a shell comment, a here-document, an embedded command substitution of the $(command) form, or a quoted string, undefined results occur. A single-quoted or double-quoted string that begins, but does not end, within the "'...'" sequence produces undefined results.

With the $(command) form, all characters following the open parenthesis to the matching closing parenthesis constitute the command. Any valid shell script can be used for command, except a script consisting solely of re-directions which produces unspecified results.

Então, por que todos dizem que os backticks foram preteridos?

Como a maioria dos casos de uso deve fazer uso do formulário parens do dólar em vez de backticks. (Depreciado no primeiro sentido acima.) Muitos dos sites mais conceituados (incluindo U & L) muitas vezes afirmam isso também, por toda parte, então é um bom conselho. Este conselho não deve ser confundido com algum plano inexistente para remover o suporte para backticks de shells.

trecho

'...' is the legacy syntax required by only the very oldest of non-POSIX-compatible bourne-shells. There are several reasons to always prefer the $(...) syntax:

...

trecho

This is the older Bourne-compatible form of the command substitution. Both the 'COMMANDS' and $(COMMANDS) syntaxes are specified by POSIX, but the latter is greatly preferred, though the former is unfortunately still very prevalent in scripts. New-style command substitutions are widely implemented by every modern shell (and then some). The only reason for using backticks is for compatibility with a real Bourne shell (like Heirloom). Backtick command substitutions require special escaping when nested, and examples found in the wild are improperly quoted more often than not. See: Why is $(...) preferred over '...' (backticks)?.

trecho

Because of these inconsistent behaviors, the backquoted variety of command substitution is not recommended for new applications that nest command substitutions or attempt to embed complex scripts.

OBSERVAÇÃO: Este terceiro trecho (acima) mostra várias situações em que os backticks simplesmente não funcionam, mas o método new dollar parens faz, começando com o seguinte parágrafo:

Additionally, the backquoted syntax has historical restrictions on the contents of the embedded command. While the newer "$()" form can process any kind of valid embedded script, the backquoted form cannot handle some valid scripts that include backquotes.

Se você continuar lendo essa seção, as falhas serão destacadas, mostrando como elas falhariam usando backticks, mas funcionariam usando a notação mais recente do dólar parens.

Conclusões

Então é preferível que você use parênteses em vez de backticks, mas na verdade não está usando algo tecnicamente "obsoleto" como em "isso vai parar de funcionar inteiramente em algum ponto planejado".

Depois de ler tudo isso, você deve ter a idéia de que é strongmente encorajado a usar parêntesis a menos que especificamente exija compatibilidade com um shell Bourne não-POSIX original real.

    
por 28.04.2014 / 16:58
12

Não é obsoleto, mas os backticks ( '...' ) é a sintaxe legada requerida apenas pelos mais antigos bourne-shells compatíveis com POSIX e $(...) é POSIX e mais preferida por várias razões:

  • As barras invertidas ( \ ) dentro dos backticks são tratadas de maneira não óbvia:

    $ 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 \
    
  • A codificação aninhada dentro de $() é muito mais conveniente:

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

    em vez de:

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

    ou escrevendo algo como:

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

    porque $() usa um contexto totalmente novo para citar

    que não é portátil, pois as shells de Bourne e Korn exigem essas barras invertidas, enquanto Bash e dash não.

  • A sintaxe para substituições de comando de aninhamento é mais fácil:

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

    do que:

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

    porque $() impõe um contexto totalmente novo para a cotação, de modo que cada substituição de comando é protegida e pode ser tratada por conta própria sem preocupação especial sobre cotação e escape. Ao usar backticks, fica mais feia e feia depois de dois níveis e acima.

    Mais alguns exemplos:

    echo 'echo 'ls''      # INCORRECT
    echo 'echo \'ls\''    # CORRECT
    echo $(echo $(ls))    # CORRECT
    
  • Resolve um problema de comportamento inconsistente ao usar backquotes:

    • echo '\$x' outputs \$x
    • echo 'echo '\$x'' outputs $x
    • echo $(echo '\$x') outputs \$x
  • A sintaxe de backticks possui restrições históricas no conteúdo do comando incorporado e não pode manipular alguns scripts válidos que incluam backquotes, enquanto o mais recente formulário $() pode processar qualquer tipo de script incorporado válido.

    Por exemplo, esses scripts incorporados válidos de outra forma não funcionam na coluna da esquerda, mas funcionam à direita IEEE :

    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 ')'
    '                              )
    

Portanto, a sintaxe para a substituição de comando $ -prefixed deve ser o método preferido, porque é visualmente claro com sintaxe limpa (melhora a legibilidade humana e de máquina), é aninhada e intuitiva, sua análise interna é separada e também é mais consistente (com todas as outras expansões que são analisadas de dentro de aspas duplas) onde os backticks são a única exceção e% O caractere' é facilmente camuflado quando adjacente a " , tornando ainda mais difícil a leitura, especialmente com fontes pequenas ou incomuns.

Fonte: Por que $(...) é preferido sobre '...' (backticks)? na BashFAQ

Veja também:

por 24.10.2015 / 19:05