Os backticks (ou seja, `cmd`) em * shells foram descontinuados?
118
Eu já vi esse comentário muitas vezes no Unix e Linux, bem como em outros sites que usam o fraseado "backticks foram descontinuados", com relação a shells como Bash & Zsh.
Pelo menos um Unix, AIX, documentou que os backticks são obsoletos . "Embora a sintaxe da cota retroativa seja aceita pelo ksh, ela é considerada obsoleta pelos padrões do X / Open Portability Guide Issue 4 e POSIX. Esses padrões recomendam que aplicativos portáteis usem a sintaxe $ (command)." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher
Eu tenho uma diferença definida em "GNU bash, versão 3.2.57 (1) -release (x86_64-apple-darwin14)" no mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )funciona, matchingLines= backtick the same stuff backticknão funciona - parece perder a barra invertida em barra invertida. (Não é o meu script ...)
denis
Respostas:
126
Existem dois significados diferentes de "obsoleto".
ser descontinuado: (principalmente de um recurso de software) pode ser usado, mas é considerado obsoleto e deve ser evitado, geralmente por ter sido substituído.
- Novo dicionário americano de Oxford
Por essa definição, os backticks estão obsoletos.
O status preterido também pode indicar que o recurso será removido no futuro.
Por essa definição, os backticks não são preteridos.
Ainda suportado:
Citando a especificação de grupo aberto nas linguagens de comando do shell , especificamente a seção "2.6.3 Substituição de comando", pode ser visto que ambas as formas de substituição de comando, backticks ( `..cmd..`) ou dollar parens ( $(..cmd..)) ainda são suportadas na medida em que a especificação é válida.
excerto
A substituição de comando permite que a saída de um comando seja substituída no lugar do próprio nome do comando. A substituição do comando ocorrerá quando o comando estiver entre os seguintes:
$(command)
or (backquoted version):`command`
O shell deve expandir a substituição do comando executando o comando em um ambiente de subcasca (consulte Ambiente de Execução do Shell) e substituindo a substituição do comando (o texto do comando mais as notas $()anexas ou de volta) pela saída padrão do comando, removendo sequências de um ou mais <newline> caracteres no final da substituição. Os caracteres <newline> incorporados antes do final da saída não devem ser removidos; no entanto, eles podem ser tratados como delimitadores de campo e eliminados durante a divisão de campo, dependendo do valor do IFS e da citação que estiver em vigor. Se a saída contiver bytes nulos, o comportamento não será especificado.
No estilo de substituição de comando entre aspas posteriores, <barra invertida> manterá seu significado literal, exceto quando seguido por: '$', ' \`' ou <barra invertida> . A pesquisa da cotação correspondente deve ser satisfeita pela primeira cotação não escapada sem aspas; durante esta pesquisa, se uma cotação não escapada for encontrada em um comentário do shell, um documento aqui, uma substituição de comando incorporada do $(command)formulário ou uma seqüência de caracteres citada, ocorrerão resultados indefinidos. Uma sequência de aspas simples ou aspas duplas que começa, mas não termina, na `...`sequência " " produz resultados indefinidos.
Com o $(command)formulário, todos os caracteres que seguem o parêntese aberto ao parêntese de fechamento correspondente constituem o comando. Qualquer script de shell válido pode ser usado para comando, exceto um script que consiste apenas em instruções adicionais que produzem resultados não especificados.
Então, por que todos dizem que os backticks foram preteridos?
Como a maioria dos casos de uso deve usar o formulário parens em dólar, em vez de reticulares. (Descontinuado no primeiro sentido acima.) Muitos dos sites mais respeitáveis (incluindo U&L) também costumam dizer isso o tempo todo, por isso são bons conselhos. Este conselho não deve ser confundido com algum plano inexistente para remover o suporte para backticks das cascas.
`...`é a sintaxe herdada exigida apenas pelos bourne-shells mais antigos e não compatíveis com POSIX. Há vários motivos para sempre preferir a $(...)sintaxe:
Essa é a forma mais antiga de substituição de comando, compatível com Bourne . As sintaxes `COMMANDS`e $(COMMANDS)são especificadas pelo POSIX, mas o último é muito preferido, embora o primeiro ainda seja muito prevalente nos scripts. As substituições de comando de novo estilo são amplamente implementadas por todos os shell modernos (e depois por alguns). O único motivo para usar backticks é a compatibilidade com um shell Bourne real (como o Heirloom). As substituições de comandos do backtick requerem escape especial quando aninhadas, e os exemplos encontrados na natureza são citados incorretamente com mais frequência do que não. Veja:
Por que $ (...) é preferido em vez de `...` (backticks)? .
Devido a esses comportamentos inconsistentes, a variedade de substituição de comando entre aspas não é recomendada para novos aplicativos que aninham substituições de comando ou tentam incorporar scripts complexos.
NOTA: Este terceiro trecho (acima) continua mostrando várias situações em que os backticks simplesmente não funcionam, mas o método mais recente de parens em dólar funciona, começando com o seguinte parágrafo:
Além disso, a sintaxe com aspas posteriores possui restrições históricas no conteúdo do comando incorporado. Embora o formulário "$ ()" mais recente possa processar qualquer tipo de script incorporado válido, o formulário com aspas posteriores não pode manipular alguns scripts válidos que incluem aspas posteriores.
Se você continuar lendo essa seção, as falhas serão destacadas, mostrando como elas falhariam ao usar backticks, mas funcionam usando a notação de parênteses mais recente.
Conclusões
Portanto, é preferível usar parênteses em dólares em vez de reticulares, mas na verdade você não está usando algo que foi tecnicamente "deprecado", pois em "isso deixará de funcionar totalmente em algum momento planejado".
Depois de ler tudo isso, você deve ter certeza de que é fortemente incentivado a usar parênteses em dólar, a menos que exija especificamente compatibilidade com um shell Bourne original não POSIX original.
@StephaneChazelas - Agreed! Continuarei dizendo às pessoas que elas estão obsoletas, mas os backticks não foram oficialmente "obsoletos" no sentido de que serão removidos ativamente da base de código de qualquer shell no futuro próximo. Pelo menos nenhum que eu saiba.
SLM
3
Minha interpretação é que as aspas são suportadas apenas porque estão muito arraigadas no código existente para serem obsoletas formalmente. Eu nunca ouvi um argumento para continuar a usá-los em novo código.
chepner
3
@ slm Sim, eu acho que você conseguiu - eu me afastei e não percebi. Não há quase nenhuma razão para usar essas coisas, exceto que pode ser um pouco mais limpo ao colocar camadas subconjuntos, por isso $( cmd `cmd`)é um pouco menos bagunçado do que $( cmd $(cmd))- é mais fácil de ler. Eu sempre considerei um recurso reprovado no software um oficialmente marcado para remoção pelo upstream - e nunca ouvi falar de algo assim. Eu não ligo - não tenho amor pelo túmulo.
precisa saber é o seguinte
3
Convém adicionar a seguinte citação a partir da lógica padrão do POSIX : Devido a esses comportamentos inconsistentes, a variedade de substituição de comando entre aspas não é recomendada para novos aplicativos que aninham substituições de comando ou tentam incorporar scripts complexos. Embora essa não seja uma depreciação formal, uma vez que a seção de justificativa é informativa e não normativa, ela sugere que o uso continuado de retalhos deve ser evitado.
jw013
15
Não está obsoleto, mas os backticks ( `...`) são a sintaxe herdada exigida apenas pelos bourne-shells mais antigos e não compatíveis com POSIX e $(...)é POSIX e mais preferido por vários motivos:
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 citação aninhada no interior $()é muito mais conveniente:
porque $()usa um contexto totalmente novo para citar
o que não é portátil, pois as conchas de Bourne e Korn exigiriam essas barras invertidas, enquanto Bash e dash não.
A sintaxe para aninhar substituições de comandos é mais fácil:
x=$(grep "$(dirname "$path")" file)
do que:
x=`grep "\`dirname \"$path\"\`" file`
como $()impõe um contexto totalmente novo para a citação, cada substituição de comando é protegida e pode ser tratada por si só, sem preocupação especial com a citação e escape. Ao usar as costas, fica cada vez mais feio depois de dois e acima dos níveis.
Ele resolve um problema de comportamento inconsistente ao usar aspas:
echo '\$x' saídas \$x
echo `echo '\$x'` saídas $x
echo $(echo '\$x') saídas \$x
A sintaxe dos backticks possui restrições históricas no conteúdo do comando incorporado e não pode manipular alguns scripts válidos que incluem aspas, enquanto o $()formulário mais recente 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 no IEEE da direita :
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 da substituição de comando$ pré-prefixada deve ser o método preferido, porque é visualmente clara com sintaxe limpa (melhora a legibilidade humana e da máquina), é aninhada e intuitiva, sua análise interna é separada e também é mais consistente (com todas as outras expansões analisadas entre aspas duplas), onde os backticks são a única exceção e o caractere é facilmente camuflado quando adjacente a uma leitura ainda mais difícil, especialmente com fontes pequenas ou incomuns.`"
cd
a um diretório para um exemplo de por que a$(...)
notação é mais fácil de usar do que as aspas reversas aninhadas.matchingLines=$( grep -n '\$-PARAMETER' ... | ... )
funciona,matchingLines= backtick the same stuff backtick
não funciona - parece perder a barra invertida em barra invertida. (Não é o meu script ...)Respostas:
Existem dois significados diferentes de "obsoleto".
Por essa definição, os backticks estão obsoletos.
Por essa definição, os backticks não são preteridos.
Ainda suportado:
Citando a especificação de grupo aberto nas linguagens de comando do shell , especificamente a seção "2.6.3 Substituição de comando", pode ser visto que ambas as formas de substituição de comando, backticks (
`..cmd..`
) ou dollar parens ($(..cmd..)
) ainda são suportadas na medida em que a especificação é válida.excerto
Então, por que todos dizem que os backticks foram preteridos?
Como a maioria dos casos de uso deve usar o formulário parens em dólar, em vez de reticulares. (Descontinuado no primeiro sentido acima.) Muitos dos sites mais respeitáveis (incluindo U&L) também costumam dizer isso o tempo todo, por isso são bons conselhos. Este conselho não deve ser confundido com algum plano inexistente para remover o suporte para backticks das cascas.
BashFAQ # 082 - Por que $ (...) é preferido em vez de `...` (backticks)?
excerto
Wiki Bash Hackers - Sintaxe obsoleta e obsoleta
excerto
Fundamentação padrão do POSIX
excerto
NOTA: Este terceiro trecho (acima) continua mostrando várias situações em que os backticks simplesmente não funcionam, mas o método mais recente de parens em dólar funciona, começando com o seguinte parágrafo:
Se você continuar lendo essa seção, as falhas serão destacadas, mostrando como elas falhariam ao usar backticks, mas funcionam usando a notação de parênteses mais recente.
Conclusões
Portanto, é preferível usar parênteses em dólares em vez de reticulares, mas na verdade você não está usando algo que foi tecnicamente "deprecado", pois em "isso deixará de funcionar totalmente em algum momento planejado".
Depois de ler tudo isso, você deve ter certeza de que é fortemente incentivado a usar parênteses em dólar, a menos que exija especificamente compatibilidade com um shell Bourne original não POSIX original.
fonte
$( cmd `cmd`)
é um pouco menos bagunçado do que$( cmd $(cmd))
- é mais fácil de ler. Eu sempre considerei um recurso reprovado no software um oficialmente marcado para remoção pelo upstream - e nunca ouvi falar de algo assim. Eu não ligo - não tenho amor pelo túmulo.Não está obsoleto, mas os backticks (
`...`
) são a sintaxe herdada exigida apenas pelos bourne-shells mais antigos e não compatíveis com POSIX e$(...)
é POSIX e mais preferido por vários motivos:As barras invertidas (
\
) dentro dos backticks são tratadas de maneira não óbvia:A citação aninhada no interior
$()
é muito mais conveniente:ao invés de:
ou escrevendo algo como:
porque
$()
usa um contexto totalmente novo para citaro que não é portátil, pois as conchas de Bourne e Korn exigiriam essas barras invertidas, enquanto Bash e dash não.
A sintaxe para aninhar substituições de comandos é mais fácil:
do que:
como
$()
impõe um contexto totalmente novo para a citação, cada substituição de comando é protegida e pode ser tratada por si só, sem preocupação especial com a citação e escape. Ao usar as costas, fica cada vez mais feio depois de dois e acima dos níveis.Mais alguns exemplos:
Ele resolve um problema de comportamento inconsistente ao usar aspas:
echo '\$x'
saídas\$x
echo `echo '\$x'`
saídas$x
echo $(echo '\$x')
saídas\$x
A sintaxe dos backticks possui restrições históricas no conteúdo do comando incorporado e não pode manipular alguns scripts válidos que incluem aspas, enquanto o
$()
formulário mais recente 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 no IEEE da direita :
Portanto, a sintaxe da substituição de comando
$
pré-prefixada deve ser o método preferido, porque é visualmente clara com sintaxe limpa (melhora a legibilidade humana e da máquina), é aninhada e intuitiva, sua análise interna é separada e também é mais consistente (com todas as outras expansões analisadas entre aspas duplas), onde os backticks são a única exceção e o caractere é facilmente camuflado quando adjacente a uma leitura ainda mais difícil, especialmente com fontes pequenas ou incomuns.`
"
Fonte: Por que é
$(...)
preferido`...`
(backticks)? no BashFAQVeja também:
fonte