Comprendre le backtick (`)

35

J'essaie la commande

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

mais il n’imprime pas comme il est supposé. Qu'est-ce que j'oublie ici?

Que signifie `(backquote / backtick) dans les commandes? semble dire que `évalue les commandes et les remplace par la sortie.

coolcric
la source
8
Notez que les backticks ne sont pas recommandés car vous perdrez la possibilité de faire des substitutions d'exécution imbriquées. Insetad, $ (somecommand) est préféré. A mon avis, cela améliore la lisibilité.
Tommy
6
@Tommy, Non, les backticks peuvent être imbriqués, mais cela devient un cauchemar évasif, surtout lors d'une double cotation également.
Stéphane Chazelas

Réponses:

52

Le texte entre les guillemets est exécuté et remplacé par le résultat de la commande (moins les caractères de fin de ligne, et notez que les comportements du shell varient lorsque la sortie contient des caractères NUL). Cela s'appelle une substitution de commande car elle est substituée par le résultat de la commande. Donc, si vous voulez imprimer 5, vous ne pouvez pas utiliser de backticks, vous pouvez utiliser des guillemets, comme echo "$b"ou tout simplement supprimer une citation et l'utiliser echo $b.

Comme vous pouvez le constater, puisque $bcontient 5, lorsque backticks bashtente d’exécuter une commande 5et qu’il n’existe aucune commande de ce type, il échoue avec un message d’erreur.

Pour comprendre comment fonctionne les backticks, essayez ceci:

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

cat /etc/passwd |head -n1devrait imprimer la première ligne du /etc/passwdfichier. Mais comme nous utilisons des backticks, cela n’imprime pas cela sur console. Au lieu de cela, il est stocké dans Avariable. Vous pouvez faire écho $Aà cela. Notez que le moyen le plus efficace d’imprimer la première ligne est l’utilisation de la commande, head -n1 /etc/passwdmais je voulais souligner que l’expression à l’intérieur des backticks ne doit pas nécessairement être simple.

Donc si la première ligne de / etc / passwd est root:x:0:0:root:/root:/bin/bash, la première commande sera remplacée dynamiquement par bash à A="root:x:0:0:root:/root:/bin/bash".

Notez que cette syntaxe est celle du shell Bourne. Citer et s'échapper devient rapidement un cauchemar, surtout lorsque vous commencez à les imbriquer. Ksh a introduit l' $(...)alternative qui est maintenant normalisée ( POSIX ) et supportée par tous les shells (même le shell Bourne d'Unix v9). Vous devriez donc $(...)plutôt les utiliser de nos jours, sauf si vous devez être portable sur de très vieux coques Bourne.

Notez également que la sortie de `...`et $(...)sont sujettes à la division de mots et à la génération de noms de fichiers, tout comme le développement de variables (en zsh, la division de mots uniquement), il faudrait donc généralement les citer dans des contextes de liste.

Krzysztof Adamski
la source
1
Bonjour @Krzysztof, c'est utile! "depuis que $ b contient 5, bash essaie d'exécuter la commande 5" est exactement ce que je cherchais
coolcric le
you can use quotation marks, like echo "$b"=> le "" fait-il quelque chose de spécial? Cela semblerait echo $bfonctionner aussi bien.
Tootsie Rolls
@Anita: En général, les guillemets font certaines choses spéciales (cela change la façon dont les caractères spéciaux sont traités - en particulier les espaces blancs), mais dans ce cas, ils peuvent être supprimés sans trop de problèmes. En effet, aucun caractère spécial n'est utilisé et la echocommande ne se soucie pas du nombre d'arguments qu'elle obtient. Par conséquent, si elle bcontient des espaces, elle obtiendra plusieurs arguments et les imprimera quand même. Ce n'est peut-être pas le cas pour d'autres commandes (en particulier lorsque variable n'est pas défini) et j'ai donc tendance à entourer les variables de guillemets.
Krzysztof Adamski
serait bien si (POSIX)serait un lien vers la norme réelle.
erikbwork
1
@ erikb85: Cette note n'a pas été ajoutée par moi mais je l'ai modifiée avec le lien que vous avez suggéré :)
Krzysztof Adamski
11

Le backtick fait exactement ce que vous dites. Vous avez défini une variable sur un entier. Lorsque vous mettez cette variable à l’arrière de backticks, bash essaie de l’exécuter en tant que commande. Comme ce n'est pas une commande, vous obtenez l'erreur que vous avez vue.

Ce que vous voulez faire, c'est simplement:

$ b=5; echo $b

Pour mieux comprendre les backticks, comparez avec:

$ b=5; a=`echo $b`; echo $a
  5
terdon
la source
8

Allez pas à pas, votre ligne devrait l'expliquer.

$ b=5; echo `$b`;
  1. définit la variable bà 5
  2. évalue $b(fonctionne efficacement 5)
  3. echoes le résultat de l'évaluation ci-dessus.

Alors oui, le résultat que vous avez est attendu. Vous évaluez le contenu d'une variable et non la commande réelle que vous pensiez être. Tout ce que vous mettez dans les backticks est simplay évalué dans un nouveau (sous) shell.

Gertvdijk
la source
salut @gertvdijk, merci pour votre message! Je pensais que `renvoie tout ce qui reste après avoir évalué son contenu. Donc, je pensais que «$ b» aurait renvoyé 5 pour que echo l’imprime
coolcric