Noções básicas sobre backtick (`)

35

Eu estou tentando o comando

$ b=5; echo `$b`;
-bash: 5: command not found

mas não imprime 5 como deveria. O que estou perdendo aqui?

O que significa `(backquote / backtick) nos comandos? Parece dizer que `avalia os comandos internos e os substitui pela saída.

coolcric
fonte
8
Observe que os backticks não são recomendados, pois você perderá a capacidade de executar substituições aninhadas. Por outro lado, $ (algum comando) é o preferido. No entanto, melhora a legibilidade.
Tommy
6
@ Tommy, Não, os backticks podem ser aninhados, mas isso se torna um pesadelo de fuga, especialmente quando as aspas são duplas.
Stéphane Chazelas

Respostas:

52

O texto entre backticks é executado e substituído pela saída do comando (menos os caracteres de nova linha à direita e lembre-se de que o comportamento do shell varia quando há caracteres NUL na saída). Isso é chamado substituição de comando porque é substituído pela saída do comando. Portanto, se você deseja imprimir 5, não pode usar reticulares, pode usar aspas, como echo "$b"ou simplesmente largar qualquer cotação e usar echo $b.

Como você pode ver, como $bcontém 5, ao usar backticks bashestá tentando executar o comando 5e, como não existe, ele falha com a mensagem de erro.

Para entender como os backticks funcionam, tente executar o seguinte:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1deve imprimir a primeira linha do /etc/passwdarquivo. Mas como usamos backticks, isso não é impresso no console. Em vez disso, é armazenado na Avariável Você pode ecoar $Apara isso. Observe que a maneira mais eficiente de imprimir a primeira linha está usando o comando, head -n1 /etc/passwdmas eu queria ressaltar que a expressão dentro dos backticks não precisa ser simples.

Portanto, se a primeira linha de / etc / passwd for root:x:0:0:root:/root:/bin/bash, o primeiro comando será substituído dinamicamente pelo bash para A="root:x:0:0:root:/root:/bin/bash".

Observe que essa sintaxe é do shell Bourne. Citar e escapar torna-se rapidamente um pesadelo, especialmente quando você os aninha. O Ksh apresentou a $(...)alternativa que agora é padronizada ( POSIX ) e suportada por todos os shells (mesmo o shell Bourne do Unix v9). Portanto, você deve usá-lo $(...)hoje em dia, a menos que precise ser portátil para cascas Bourne muito antigas.

Observe também que a saída `...`e $(...)está sujeita à divisão de palavras e geração de nome de arquivo, assim como a expansão variável (em zsh, somente divisão de palavras), portanto, geralmente, elas precisam ser citadas em contextos de lista.

Krzysztof Adamski
fonte
11
Oi @Krzysztof, isso é útil! "desde que $ b contém 5, o bash está tentando executar o comando 5" é exatamente o que eu estava procurando
coolcric 17/09/12
you can use quotation marks, like echo "$b"=> o "" faz algo especial? Parece echo $bque funcionaria tão bem.
quer
@ Anita: Em geral, as aspas fazem algumas coisas especiais (isso muda a maneira como os caracteres especiais são tratados - especialmente os espaços em branco), mas, neste caso, eles podem ser descartados sem muitos problemas. Isso ocorre porque nenhum caractere especial é usado e o echocomando não se importa com o número de argumentos que obtém; portanto, se bhouver alguns espaços, ele receberá vários argumentos e ainda os imprimirá. Pode não ser o caso de outros comandos (especialmente quando a variável não está definida), por isso costumo sempre colocar variáveis ​​entre aspas.
Krzysztof Adamski
seria bom se (POSIX)fosse um link para o padrão real.
Erikbwork
11
@ erikb85: Esta nota não foi adicionado por mim, mas eu editei com o link como você sugeriu :)
Krzysztof Adamski
11

O backtick faz exatamente o que você diz. Você definiu uma variável para um número inteiro. Quando você coloca essa variável dentro dos backticks, o bash tenta executá-la como um comando. Como não é um comando, você recebe o erro que viu.

O que você quer fazer é simplesmente:

$ b=5; echo $b

Para entender melhor os backticks, compare com:

$ b=5; a=`echo $b`; echo $a
  5
terdon
fonte
8

Indo passo a passo sua linha deve explicar isso.

$ b=5; echo `$b`;
  1. define variável bpara 5
  2. avalia $b(executa efetivamente 5)
  3. echoé o resultado da avaliação acima.

Então, sim, o resultado obtido é esperado. Você está avaliando o conteúdo de uma variável, não o comando real que você pensou que era. Tudo o que você coloca nos backticks é avaliado pelo simplay (executado) em um novo (sub) shell.

gertvdijk
fonte
oi @gertvdijk, obrigado por seu post! Eu estava pensando que `retorna o que resta depois de avaliar seu conteúdo. Então, eu pensei que '$ b' teria retornado 5 para eco para imprimi-lo
coolcric 17/09/2012