web-dev-qa-db-fra.com

Évaluation d'une chaîne dans un script shell

Je suis ce guide de script bash shell:

Dans la section Comparaisons numériques, il cite un exemple:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

Ce qui semble se produire ci-dessus, c'est que nous stockons une chaîne de commandes dans une variable bash, puis nous appelons echo sur la variable. Ce qui semble se produire, c'est que la chaîne est évaluée et que la commande wc est exécutée et renvoie le nombre de lignes au terminal de contrôle.

Ok, je lance donc mon terminal dans Ubuntu 12.04 et essaie quelque chose de similaire:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Attendez une seconde, cela n’a pas évalué la chaîne et renvoyé le nombre de lignes. Cela a juste fait écho la chaîne de retour au terminal. Pourquoi ai-je eu des résultats différents?

8
JohnMerlino

Vous devez utiliser des backticks pour évaluer l'expression.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

Si vous voulez voir seulement "1" dans la sortie, utilisez la commande

$ num=`cat sample.txt | wc -l`
$ echo $num
1

Et fonctionne aussi:

$ num=`wc -l < sample.txt`
$ echo $num
1

Pour plus d'informations, voir Différences entre les guillemets doubles "", les guillemets simples '' et les piqûres croisées "sur la ligne de commande?

2
Danatela

S'il vous plaît noter ce symbole:

'

Simple citation

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

et

`

Backquote

   Command substitution allows the output of a command to replace the com‐
   mand name.  There are two forms:

          $(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.

Donc, le Backquote renvoie le résultat de la commande à la sortie standard. C'est pourquoi

`wc -l sample.txt`

renvoie les résultats de la commande, tandis que

'wc -l sample.txt'

il suffit de retourner "wc -l sample.txt" comme chaîne habituelle

Considérez ceci comme exemple:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

Et maintenant, echo les trois variables:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
5
c0rp

Si vous voulez capturer la sortie d'une commande dans une variable, vous devez utiliser des backticks `` ou placer la commande dans $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Notez que la chaîne est en fait évaluée au moment de la déclaration de la variable, pas lorsque vous l’appuyez sur un écho. La commande est en fait exécutée dans la $() ou les backticks et le résultat de cette commande est enregistré en tant que valeur de la variable.

En général, vous devriez toujours utiliser $() au lieu de backticks qui sont déconseillés et uniquement pour des raisons de compatibilité et beaucoup plus limités. Vous ne pouvez pas, par exemple, imbriquer des commandes dans des backticks, mais vous pouvez avec $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

Voir ce fil sur U & L pour plus de détails sur la raison pour laquelle `` devrait être évité.

4
terdon