Qual é a diferença entre $ (command) e `command` na programação shell?


258

Para armazenar a saída de um comando como uma variável em sh / ksh / bash, você pode:

var=$(command)

ou

var=`command`

Qual a diferença, se houver, entre os dois métodos?


29

Você encontrará o problema aninhado detalhado na Diretriz de codificação Git: veja minha resposta abaixo .
VonC

Respostas:


274

Os backticks / gravemarks foram descontinuados em favor da $()substituição de comandos, porque $()podem facilmente se aninhar em si mesmos , como em $(echo foo$(echo bar)). Existem outras diferenças, como como as barras invertidas são analisadas na versão backtick / gravemark, etc.

Consulte o BashFAQ / 082 por vários motivos para sempre preferir a sintaxe $ (...).

Consulte também a especificação POSIX para obter informações detalhadas sobre as várias diferenças.


25
Bom link, mas esse texto não substitui as aspas a favor $(...)- apenas as observa como alternativas.
Norman Grey

24
@NormanGray POSIX podem não dizer a palavra obsoleta mas diz "the backquoted variety of command substitution is not recommended"que é apenas uma maneira prolixo de dizer obsoleto IMHO
SiegeX

11
O POSIX não reprovou os backticks, mas foi adicionado $(...)como um método alternativo. Não há nenhum bug de implementação conhecido com backticks, mas existem muitos erros de implementação conhecidos $(...) . Portanto, para problemas de portabilidade, é recomendável usar backticks para chamadas não aninhadas. $(...)precisa de um analisador recursivo, mas isso não foi usado com o ksh86 que introduziu o recurso. Verifique in-ulm.de/~mascheck/various/cmd-subst para obter uma lista das implementações corretas. Um shell em conformidade precisa suportar todos os casos, exceto o caso D.2.
schily

2
Há outras coisas no POSIX que precisam ser vistas deprecated, por exemplo, o uso waitpid()disso impede que você veja os 32 bits completos do exit()parâmetro, mas todos os shells, exceto o recente Bourne Shell, ainda usam em waitpid()vez da waitid()chamada que está disponível desde 26 anos.
schily

O link na resposta sugere que existem algumas diferenças entre os backticks e $(), o que é mais explicado nesta parte da documentação . As diferenças não são apenas sobre o aninhamento.
Algum programador cara,

39

Eles se comportam da mesma maneira. A diferença é sintática: é mais fácil aninhar do $()que ``:

listing=$(ls -l $(cat filenames.txt))

vs.

listing=`ls -l \`cat filenames.txt\``

10
echo $(echo \$abc)não é o mesmo que echo `echo \$abc`‍- também existem diferenças de $(echo \`)e $(echo \\)
Peter.O

Outra diferença é: echo foo `#comment`vs echo foo $(#comment). O segundo não funciona. (Usado para comentar em um comando multi-line.)
wisbucky

27

Julho de 2014: o commit f25f5e6 (de Elia Pinto ( devzero2000) , abril de 2014, Git 2.0) adiciona ao problema de aninhamento:

O formulário com aspas posteriores é o método tradicional de substituição de comandos e é suportado pelo POSIX.
No entanto, todos os usos, exceto os mais simples, tornam-se complicados rapidamente.
Em particular, substituições de comandos incorporados e / ou o uso de aspas duplas requerem escape cuidadoso com o caractere de barra invertida
.

É por isso que o git / Documentation / CodingGuidelines menciona:

Nós preferimos $( ... )a substituição de comandos; ao contrário de ``, aninha adequadamente .
Deveria ter sido como Bourne escreveu desde o primeiro dia, mas infelizmente não é.

thiton comentou :

É por isso `echo `foo`` que não funcionará em geral por causa da ambiguidade inerente, pois cada um ``pode ser aberto ou fechado.
Pode funcionar em casos especiais devido à sorte ou recursos especiais.


Atualização em janeiro de 2016: o Git 2.8 (março de 2016) se livra completamente dos backticks.

Consulte confirmar ec1b763 , confirmar 9c10377 , confirmar c7b793a , confirmar 80a6b3f , confirmar 9375dcf , confirmar e74ef60 , confirmar 27fe43e , cometer 2525c51 , cometer becd67f , cometer a5c98ac , cometer 8c311f9 , cometer 57da049 , cometer 1d9e86f , cometer 78ba28d , cometer efa639f , cometer 1be2fa0 , cometer 38e9476 , confirmar 8823d2f , confirmar 32858a0 , confirmar cd914d8(12 de janeiro de 2016) por Elia Pinto ( devzero2000) .
(Mesclado por Junio ​​C Hamano - gitster- no commit e572fef , 22 de janeiro de 2016)

Do Git 2.8 em diante, é tudo $(...), não mais `...`.


2
$()também é especificado pelo POSIX - uma citação que descreve os backticks como "suportados pelo POSIX" de modo a sugerir que isso é exclusivo para eles é enganosa. É apenas (Bourne pré-POSIX da década de 1970) que os backticks são a única sintaxe suportada.
Charles Duffy

25

Quando o formulário de retorno anterior é usado, a barra invertida mantém seu significado literal, exceto quando seguido por $, `ou \. O primeiro back-tick não precedido por uma barra invertida finaliza a substituição do comando.

Ao usar o $(command)formulário mais recente , todos os caracteres entre parênteses formam o comando; nenhum é tratado especialmente.

Ambos os formulários podem ser aninhados, mas a variedade de recuo requer o seguinte formulário.

`echo \`foo\`` 

Ao contrário de:

$(echo $(foo))

1
Correção menor, a versão do backtick e a $()versão são compatíveis com POSIX.
SiegeX 16/01

5

Há pouca diferença, exceto os caracteres não escapados que você pode usar dentro do comando. Você pode até colocar comandos `...` dentro de $ (...) (e vice-versa) para uma substituição de comando mais complicada em dois níveis.

Há uma interpretação ligeiramente diferente do caractere / operador de barra invertida. Entre outras coisas, quando nidificação `...` comandos de substituição, você deve escapar as internas ` caracteres com \, enquanto que com $ () substition que compreende a nidificação automaticamente.


0

"Qual a diferença entre os dois métodos?"

Tome atenção a este comportamento:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

Você obterá estes resultados:

$A
A_VARIABLE

 

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.