Les backticks (ie `cmd`) dans les shells * sh sont-ils déconseillés?

118

J'ai vu ce commentaire à de nombreuses reprises sur Unix et Linux ainsi que sur d'autres sites qui utilisent l'expression "les backticks ont été déconseillés", en ce qui concerne des shells tels que Bash & Zsh.

Cette déclaration est vraie ou fausse?

slm
la source
Voir Pourquoi les guillemets arrières dans un script shell ne m'aident pas cdà accéder à un répertoire pour un exemple de la raison pour laquelle la $(...)notation est plus facile à utiliser que les guillemets arrières imbriqués.
Jonathan Leffler
2
ligne de frappe ici
Trevor Boyd Smith
1
Au moins un Unix, AIX, a documenté que les backticks sont obsolètes . "Bien que la syntaxe backquote soit acceptée par ksh, elle est considérée comme obsolète par les normes X / Open Portability Guide Issue 4 et POSIX. Ces normes recommandent aux applications portables d’utiliser la syntaxe $ (commande)." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher
J'ai une nette différence dans "GNU bash, version 3.2.57 (1) - release (x86_64-apple-darwin14)" sur mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )fonctionne, matchingLines= backtick the same stuff backtickne fonctionne pas - semble perdre la barre oblique inverse dans la barre oblique inverse. (Ce n'est pas mon script ...)
denis

Réponses:

126

Il existe deux sens différents de "obsolète".

être déconseillé: (principalement d'une fonctionnalité logicielle) être utilisable mais considéré comme obsolète et à éviter, en raison de son remplacement.

- Nouveau dictionnaire américain Oxford

Par cette définition, les backticks sont obsolètes.

Le statut obsolète peut également indiquer que la fonctionnalité sera supprimée à l'avenir.

- Wikipedia

Par cette définition, les backticks ne sont pas obsolètes.

Toujours supporté:

En citant la spécification de groupe ouvert sur les langages de commande Shell , plus précisément à la section "2.6.3 Substitution de commandes", il apparaît que les deux formes de substitution de commande, backticks ( `..cmd..`) ou dollar parens ( $(..cmd..)) sont toujours prises en charge dans la mesure où la spécification est appliquée .

extrait

La substitution de commande permet de substituer la sortie d’une commande à la place du nom de la commande elle-même. La substitution de commande doit se produire lorsque la commande est enfermée comme suit:

          $(command)

          or (backquoted version):

          `command`

La coquille doit élargir la substitution de commande par la commande d' exécution dans un environnement de sous - couche (voir Execution Environment Shell) et en remplaçant la substitution de commande (le texte de commande ainsi que l'enceinte $()ou backquotes) à la sortie standard de la commande, en supprimant des séquences d'un ou plusieurs <nouvelle ligne> caractères à la fin de la substitution. Les caractères <nouvelle ligne> incorporés avant la fin de la sortie ne doivent pas être supprimés; Cependant, ils peuvent être traités comme des délimiteurs de champ et éliminés lors de la scission de champ, en fonction de la valeur de IFS et de la citation qui est en vigueur. Si la sortie contient des octets nuls, le comportement n'est pas spécifié.

Dans le style de substitution de commande passé entre guillemets, la <barre oblique inversée> conserve son sens littéral, sauf si elle est suivie de '$', ' \`' ou <barre oblique inversée> . La recherche de la citation correspondante doit être satisfaite par la première citation non échappée non échappée; Au cours de cette recherche, si une citation arrière non échappée est rencontrée dans un commentaire de shell, un document here, une substitution de commande incorporée du $(command)formulaire ou une chaîne entre guillemets, des résultats non définis se produisent. Une chaîne entre guillemets simples ou guillemets doubles qui commence sans se terminer dans la `...`séquence " " produit des résultats non définis.

Avec le $(command)formulaire, tous les caractères suivant la parenthèse ouverte à la parenthèse fermante correspondante constituent la commande. Tout script shell valide peut être utilisé pour la commande, à l'exception d'un script composé uniquement de re-directions qui produisent des résultats non spécifiés.

Alors, pourquoi tout le monde dit que les backticks ont été déconseillés?

Parce que la plupart des cas d'utilisation devraient utiliser la forme dollar parens plutôt que les backticks. (Déconseillé dans le premier sens ci-dessus.) La plupart des sites les plus réputés (y compris U & L) affirment souvent cela aussi, tout au long de leur propos, c'est donc un conseil judicieux. Ce conseil ne doit pas être confondu avec un plan inexistant visant à supprimer le soutien des piqûres arrière des coquilles.

  • BashFAQ # 082 - Pourquoi $ (...) est-il préféré à `...` (backticks)?

    extrait

    `...`est la syntaxe héritée requise par le très ancien bourne-shell non compatible POSIX. Il y a plusieurs raisons pour toujours préférer la $(...)syntaxe:

    ...

  • Wiki Bash Hackers - Syntaxe obsolète et obsolète

    extrait

    Il s'agit de l'ancienne forme compatible avec Bourne de la substitution de commande . Les syntaxes `COMMANDS`et $(COMMANDS)sont spécifiés par POSIX, mais le dernier est fortement préféré, bien que le premier soit malheureusement encore très répandu dans les scripts. Les substitutions de commandes de style nouveau sont largement implémentées par chaque shell moderne (et même certains). La seule raison d’utiliser Backticks est la compatibilité avec un vrai shell Bourne (comme Heirloom). Les substitutions de commandes Backtick nécessitent un échappement spécial lorsqu'elles sont imbriquées, et les exemples trouvés dans la nature sont mal cités plus souvent qu'autrement. Voir: Pourquoi est-ce que $ (...) est préféré à `...` (backticks)? .

  • Logique standard POSIX

    extrait

    En raison de ces comportements incohérents, la variété de substitution de commandes mentionnée en arrière n'est pas recommandée pour les nouvelles applications qui imbriquent des substitutions de commandes ou tentent d'incorporer des scripts complexes.

Remarque: ce troisième extrait (ci-dessus) montre plusieurs situations où les backtick ne fonctionnent tout simplement pas, mais la méthode la plus récente dollar parens fonctionne, en commençant par le paragraphe suivant:

De plus, la syntaxe backcoted a des restrictions historiques sur le contenu de la commande incorporée. Alors que le nouveau formulaire "$ ()" peut traiter n’importe quel type de script incorporé valide, le formulaire avec rétro-notation ne peut pas gérer certains scripts valides incluant des guillemets.

Si vous continuez à lire cette section, les échecs sont mis en surbrillance et montrent comment ils échoueraient en utilisant des backticks, mais ils fonctionnent en utilisant la nouvelle notation dollar parens.

Conclusions

Il est donc préférable que vous utilisiez des dollars parens plutôt que des backticks, mais vous n'utilisez pas quelque chose techniquement "déprécié", car dans "cela cessera de fonctionner complètement à un moment planifié".

Après avoir lu tout cela, vous devriez penser que l’utilisation de dollar parens est vivement recommandée, à moins que vous n’exigiez une compatibilité avec un véritable shell Bourne non POSIX.

slm
la source
26
Selon la plupart des significations de obsolète , je dirais (et vous) que les backticks sont déconseillés. C'est surtout une question de terminologie.
Stéphane Chazelas
4
@ StephaneChazelas - D'accord! Je continuerai à dire à ppl qu'ils sont obsolètes, mais les backticks n'ont pas été officiellement "déconseillés" dans le sens où ils vont être activement supprimés de la base de code de tout shell dans un avenir proche. Au moins aucun que je sache.
slm
3
Mon interprétation est que les citations arrières sont prises en charge uniquement parce qu'elles sont trop enracinées dans le code existant pour être obsolètes. Je n'ai jamais entendu un argument pour continuer à les utiliser dans le nouveau code.
Chepner
3
@slm Ouais, je suppose que vous l'avez compris - je me suis échappé et je n'ai pas remarqué. Il n'y a presque aucune raison d'utiliser ces choses, sauf qu'il peut être un peu plus propre lors de la superposition sous - couches donc $( cmd `cmd`)est juste un peu moins salissant que $( cmd $(cmd))- il est plus facile à lire. J'ai toujours toujours considéré une fonctionnalité obsolète dans un logiciel comme une fonctionnalité officiellement désignée comme étant supprimée par l'amont - et je n'ai jamais entendu parler de ce genre de chose. Je m'en fiche, je n'ai aucun amour pour la tombe.
mikeserv
3
Vous voudrez peut-être ajouter la citation suivante tirée de la logique standard POSIX : En raison de ces comportements incohérents, la variété de substitution de commandes inversée n'est pas recommandée pour les nouvelles applications qui imbriquent des substitutions de commandes ou tentent d'incorporer des scripts complexes. Bien qu’il ne s’agisse pas d’une dépréciation formelle puisque la section de la justification est informative et non normative, cela suggère que l’utilisation continue de backtick devrait être évitée.
jw013
15

Ce n'est pas obsolète, mais backticks ( `...`) est la syntaxe héritée requise uniquement par le très ancien bourge-shell non compatible $(...)POSIX et est POSIX et plus préféré pour plusieurs raisons:

  • Les \barres obliques inversées ( ) à l'intérieur sont des manipulations non évidentes:

    $ 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 \\
  • La citation imbriquée à l'intérieur $()est beaucoup plus pratique:

    echo "x is $(sed ... <<<"$y")"

    au lieu de:

    echo "x is `sed ... <<<\"$y\"`"

    ou écrire quelque chose comme:

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    car $()utilise un contexte entièrement nouveau pour citer

    qui n'est pas portable, car les obus Bourne et Korn auraient besoin de ces barres obliques inverses, contrairement à Bash et Dash.

  • La syntaxe de substitution des commandes est plus simple:

    x=$(grep "$(dirname "$path")" file)

    que:

    x=`grep "\`dirname \"$path\"\`" file`

    car $()applique un contexte entièrement nouveau pour les citations, ainsi chaque substitution de commande est protégée et peut être traitée seule, sans souci particulier pour les citations et les échappements. Lors de l'utilisation de backticks, il devient plus laid et plus laid après deux niveaux et plus.

    Quelques exemples supplémentaires:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
  • Cela résout un problème de comportement incohérent lors de l'utilisation de citations arrières:

    • echo '\$x' les sorties \$x
    • echo `echo '\$x'` les sorties $x
    • echo $(echo '\$x') les sorties \$x
  • La syntaxe Backticks a des restrictions historiques sur le contenu de la commande incorporée et ne peut pas gérer certains scripts valides incluant des guillemets, tandis que le nouveau $()formulaire peut traiter tout type de script incorporé valide.

    Par exemple, ces scripts incorporés par ailleurs valides ne fonctionnent pas dans la colonne de gauche, mais fonctionnent dans la colonne IEEE de droite :

    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 ')'
    `                              )

Par conséquent, la syntaxe pour la substitution de commande$ -prefixed devrait être la méthode préférée, car elle est claire visuellement avec une syntaxe propre (améliore la lisibilité pour l'homme et la machine), qu'elle est imbriquée et intuitive, que son analyse interne est distincte et qu'elle est également plus cohérente (avec toutes les autres extensions qui sont analysées à partir de guillemets) où les guillemets sont la seule exception et le caractère est facilement camouflé lorsqu'il est adjacent, ce qui le rend encore plus difficile à lire, en particulier avec des polices de petite taille ou inhabituelles.`"

Source: Pourquoi est $(...)préféré sur `...`(backticks)? chez BashFAQ

Voir également:

Kenorb
la source