Qual é a diferença entre $ (stuff) e `stuff`?

265

Existem duas sintaxes para substituição de comando: com parênteses em dólar e com reticulares. Em execução top -p $(pidof init)e top -p `pidof init`dá a mesma saída. Existem duas maneiras de fazer a mesma coisa ou existem diferenças?

tshepang
fonte
18
Veja também: BashFAQ / 082 .
Dennis Williamson
43
Por um segundo, pensei que fosse uma pergunta sobre jQuery.
David Murdoch
O resultado pode depender do shell - alguns suportam ambos.
Artdanil

Respostas:

360

As citações de estilo antigo ` `tratam barras invertidas e aninhadas um pouco diferentes. O novo estilo $()interpreta tudo no meio ( )como um comando.

echo $(uname | $(echo cat))
Linux

echo `uname | `echo cat``
bash: command substitution: line 2: syntax error: unexpected end of file
echo cat

funciona se as aspas aninhadas forem escapadas:

echo `uname | \`echo cat\``
Linux

barra invertida divertida:

echo $(echo '\\')
\\

echo `echo '\\'`
\

O novo estilo $()se aplica a todos os shells compatíveis com POSIX .
Como mouviciel apontou, o estilo antigo ` `pode ser necessário para as conchas mais antigas.

Além do ponto de vista técnico, o estilo antigo ` `também tem uma desvantagem visual:

  • Difícil perceber: I like $(program) better than `program`
  • Facilmente confundido com uma única citação: '`'`''`''`'`''`'
  • Não é tão fácil de digitar (talvez nem no layout padrão do teclado)

(e o SE usa ` `para fins próprios, foi difícil escrever esta resposta :)

abanar
fonte
10
A única coisa que eu gostaria de acrescentar, é que eu chamo de '(' a parêntese, não um suporte (que é '[').
Kendall Helmstetter Gelner
@Kendall: e aqui eu pensei '{' foi o suporte esquerdo durante todos esses anos ...
Samb
5
@Sam: { }é geralmente chamado de "chaves" ou "chaves" en.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn Schou-Rode
2
Também me refiro a '{' como chaves. Embora pareça estranho, você precisa adicionar o qualificador "curly" se você chamar as outras coisas de colchetes ... Acho que é só porque elas realmente se enrolam.
Kendall Helmstetter Gelner
1
@slim Eu não sei nos teclados dos EUA / Reino Unido, mas nos teclados espanhóis `é uma chave morta, então eu tenho que digitar um backtick duplo (algo que geralmente esqueço que posso fazer) ou backtick e espaço, o que é um dor.
precisa saber é o seguinte
41

A diferença óbvia que observo é que você não pode aninhar backticks enquanto pode aninhar $(). Talvez ambos existam por motivos legados. Da mesma forma, os comandos .e sourcesão sinônimos.

balki
fonte
10
Algumas conchas derivadas de Bourne não reconhecem source. Dash é um exemplo.
Dennis Williamson
14
Isso não é verdade. Você pode aninhar backtick para qualquer nível, apenas mais dolorosamente. Note-se que tanto $(...)e `...`são padrão (o último sendo preterido), enquanto .é padrão, mas nãosource
Stéphane Chazelas
3
Correção, somente (t)csheles não podem ser aninhados. (t)cshnão suporte $(...)embora. Eles suportam source(e não .) embora.
Stéphane Chazelas
28

$()não funciona com shell Bourne antigo. Mas faz anos décadas desde que trabalhei com a velha concha Bourne.

mouviciel
fonte
Velho como nos anos 70 e início dos 80, correto?
Christopher
6

Outra observação: $()usará mais recursos do sistema do que backticks, mas é um pouco mais rápido.

No domínio do script de shell do Unix , Randal K. Michael fez um teste em um capítulo chamado "24 maneiras de processar um arquivo linha por linha".

cuonglm
fonte
2
Esta afirmação é um absurdo. Não há razão para que seja mais rápido, pois está apenas usando uma notação diferente para o analisador.
schily
@ Schily: Talvez, apenas cite o livro, você pode lê-lo para mais detalhes.
cuonglm
3
Eu tenderia a concordar com @schily ... por que seriam necessários mais recursos?
Curinga
2
@ Wildcard, suponho que é porque $()torna o seu script um byte maior do que se fosse usado `(supondo que você não os aninhe e não use barras invertidas). Quanto ao que seria mais rápido de analisar, isso variaria entre as conchas e seria irrelevante e desprezível se comparado ao custo de criação de um tubo e bifurcação do processo que implica substituição de comando.
Stéphane Chazelas
5

Para adicionar ao que os outros disseram aqui, você pode usar os backticks para simular comentários embutidos:

echo foo `# I'm a comment!` bar

A saída é: foo bar.

Consulte o seguinte para obter mais informações: https://stackoverflow.com/a/12797512 (Observe também os comentários abaixo dessa postagem.)

phk
fonte
1

A $()sintaxe não funcionará com o antigo shell bourne.
Com shells mais novos ` `e $()equivalentes, $()é muito mais conveniente quando você precisa aninhar vários comandos.

Por exemplo :

echo $(basename $(dirname $(dirname /var/adm/sw/save )))

é mais fácil digitar e depurar do que:

echo `basename \`dirname \\\`dirname /var/adm/sw/save \\\`\``
Emmanuel
fonte
1
Embora $ () possa parecer bom, é uma dor de cabeça ao implementar um analisador relacionado, pois requer um analisador recursivo duplo.
schily
6
@schily Por outro lado, o que seria uma concha sem um bom analisador.
Emmanuel
1
O problema é que você precisa saber onde a sequência termina antes de chamar o analisador. Isso é relativamente simples com os backticks, mas é difícil com colchetes, pois eles são usados ​​para vários fins no shell. Portanto, você precisa do analisador duas vezes e de uma maneira que não exista no Bourne Shell.
schily