Quel est l'avantage d'utiliser $ () au lieu de backtincs dans les scripts shell?

StackOverflow https://stackoverflow.com/questions/9449778

  •  13-11-2019
  •  | 
  •  

Question

Il existe deux façons de capturer la sortie de la ligne de commande dans bash:

  1. Backtincs de shell bourne hérité ``:

     var=`command`
    
  2. $() Syntaxe (qui, pour autant que je sache, est spécifique à Bash, ou du moins pas pris en charge par des anciens coquilles non-Posix comme Bourne original)

     var=$(command)
    

Y a-t-il un avantage à utiliser la deuxième syntaxe par rapport aux backticks? Ou les deux sont-ils entièrement 100% équivalents?

Était-ce utile?

La solution

Le majeur est la capacité de nid eux, commandes dans les commandes, sans perdre votre santé mentale en essayant de déterminer si une forme de s'échapper fonctionnera sur les backticks.

Un exemple, bien que quelque peu artificiel:

deps=$(find /dir -name $(ls -1tr 201112[0-9][0-9]*.txt | tail -1l) -print)

ce qui vous donnera une liste de tous les fichiers dans le /dir Arbre d'annuaire qui a le même nom que le premier fichier texte daté de décembre 2011 (un).

Un autre exemple serait quelque chose comme obtenir le nom (pas le chemin complet) du répertoire parent:

pax> cd /home/pax/xyzzy/plugh
pax> parent=$(basename $(dirname $PWD))
pax> echo $parent
xyzzy

(un) Maintenant que spécifique La commande peut ne pas fonctionner réellement, je n'ai pas testé la fonctionnalité. Donc, si vous me votez pour cela, vous avez perdu de vue l'intention :-) Cela signifie exactement une illustration de la façon dont vous pouvez nicher, pas comme un extrait prêt pour la production sans bug.

Autres conseils

Supposons que vous souhaitiez trouver le répertoire Lib correspondant à où gcc est installé. Tu as le choix:

libdir=$(dirname $(dirname $(which gcc)))/lib

libdir=`dirname \`dirname \\\`which gcc\\\`\``/lib

Le premier est plus facile que le second - utilisez le premier.

Les backtincs (`...`) est la syntaxe héritée requise par unique $(...) est POSIX et plus préféré pour plusieurs raisons:

  • Barreaux réalisateurs (\) Les backtincs à l'intérieur sont traités de manière non évidente:

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

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

    à la place 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

    Ce qui n'est pas portable, car Bourne et Korn Shels nécessiteraient ces barreaux de bar, tandis que Bash et Dash ne le font pas.

  • La syntaxe pour les substitutions de commande de nidification est plus facile:

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

    que:

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

    car $() Applique un contexte entièrement nouveau pour la citation, de sorte que chaque substitution de commande est protégée et peut être traitée seule sans préoccupation particulière concernant la citation et l'échappement. Lorsque vous utilisez des backticks, il devient plus laid et plus laid après deux niveaux et au-dessus.

    Quelques exemples supplémentaires:

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

    • echo '\$x' les sorties \$x
    • echo `echo '\$x'` les sorties $x
    • echo $(echo '\$x') les sorties \$x
  • La syntaxe des backticks a des restrictions historiques sur le contenu de la commande intégrée et ne peut pas gérer certains scripts valides qui incluent des backquotes, tandis que le plus récent $() Le formulaire peut traiter tout type de script intégré valide.

    Par exemple, ces scripts intégrés autrement valides ne fonctionnent pas dans la colonne de gauche, mais fonctionnent à droiteIEEE:

    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 $-préfixé substitution de commandement devrait être la méthode préférée, car elle est visuellement claire avec une syntaxe propre (améliore la lisibilité humaine et machine), elle est niditable et intuitive, son analyse intérieure est séparée, et elle est également plus cohérente (avec toutes les autres extensions qui sont analysées de l'intérieur Double-Quotes) où les backticks sont la seule exception et ` Le caractère est facilement camouflé lorsqu'il est adjacent à " Le rendre encore plus difficile à lire, en particulier avec des polices petites ou inhabituelles.

La source: Pourquoi est-ce $(...) préféré à `...` (backtincs)? à Bashfaq

Voir également:

De l'homme bash:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com-
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.  Embedded newlines are not deleted, but they
   may  be  removed during word splitting.  The command substitution $(cat
   file) can be replaced by the equivalent but faster $(< file).

   When the old-style backquote form of substitution  is  used,  backslash
   retains  its  literal  meaning except when followed by $, `, or \.  The
   first backquote not preceded by a backslash terminates the command sub-
   stitution.   When using the $(command) form, all characters between the
   parentheses make up the command; none are treated specially.

En plus des autres réponses,

$(...)

se démarque visuellement mieux que

`...`

Les backticks ressemblent trop à des apostrophes; Cela varie en fonction de la police que vous utilisez.

(Et, comme je viens de le remarquer, les backticks sont beaucoup plus difficiles à saisir dans des échantillons de code en ligne.)

$() permet la nidification.

out=$(echo today is $(date))

Je pense que Backticks ne le permet pas.

C'est la norme POSIX qui définit le $(command) forme de substitution de commandement. La plupart des obus utilisés aujourd'hui sont conformes à POSIX et prennent en charge cette forme préférée à la notation de backttick archaïque. La substitution de commandement La section (2.6.3) du document de langue Shell décrit ceci:

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

$(commande)

ou (version backquote):

`commande`

Le shell doit étendre la substitution de commandement en exécutant commandedans un environnement de sous-coquille (voir Environnement d'exécution du shell) et remplacer la substitution de commande (le texte de commande plus le "$ ()" ou les backQuotes enfermés) avec la sortie standard de la commande, supprimant les séquences d'un ou plusieurs <newline> Personnages à la fin de la substitution. Embarqué <newline> Les caractères 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 du fractionnement du champ, en fonction de la valeur des IF et de la citation qui est en vigueur. Si la sortie contient des octets NULL, le comportement n'est pas spécifié.

Dans le style de substitution de commandement sur backquote, <backslash> conservera sa signification littérale, sauf lorsqu'elle est suivie de: '$' , '`', ou <backslash>. La recherche du backquote assorti doit être satisfaite par le premier backquote non escuit non inscrit; Au cours de cette recherche, si un backquote non insuffisant est rencontré dans un commentaire de coquille, un document ici, une substitution de commande intégrée du $ (commande) Formulaire, ou une chaîne citée, des résultats non définis se produisent. Une chaîne à un seul qute ou double citée qui commence, mais ne se termine pas, dans le "`...`"La séquence produit des résultats non définis.

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

Les résultats de la substitution de commandement ne doivent pas être traités pour une expansion supplémentaire de Tilde, une expansion des paramètres, une substitution de commandement ou une expansion arithmétique. Si une substitution de commande se produit à l'intérieur des doubles quotidiens, le fractionnement de champ et l'expansion du chemin de chemin ne doivent pas être effectués sur les résultats de la substitution.

La substitution de commande peut être imbriquée. Pour spécifier la nidification dans la version backquote, l'application doit précéder les backQuotes intérieurs avec <backslash> personnages; par exemple:

\`commande\`

La syntaxe du langage de commande shell a une ambiguïté pour les extensions commençant par "$((", qui peut introduire une expansion arithmétique ou une substitution de commande qui commence par une sous-coquille. L'expansion arithmétique a une priorité; substitution si elle détermine qu'elle ne peut pas analyser l'expansion comme une expansion arithmétique. Le shell n'a pas besoin d'évaluer les extensions imbriquées lors de l'exécution de cette détermination. S'il rencontre la fin de l'entrée sans avoir déjà déterminé qu'il ne peut pas analyser l'expansion comme une expansion arithmétique, la Shell doit traiter l'expansion comme une expansion arithmétique incomplète et signaler une erreur de syntaxe. Une application conformée doit s'assurer qu'elle sépare le "$(" et '(«En deux jetons (c'est-à-dire les séparer avec un espace blanc) dans une substitution de commande qui commence par une sous-coquille. Par exemple, une substitution de commande contenant une seule sous-coquille pourrait être écrite comme suit:

$( (commande) )

C'est une question héritée, mais j'ai trouvé un exemple parfaitement valable de $(...) plus de `...`.

J'utilisais un bureau distant sur Windows exécutant Cygwin et je voulais itérer sur le résultat d'une commande. Malheureusement, le personnage de Backtick était impossible à entrer, soit en raison de la chose de bureau distante, soit du cygwin lui-même.

Il est sain d'esprit de supposer qu'un signe en dollars et des parenthèses seront plus faciles à taper dans des configurations aussi étranges.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top