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

8

Je suis ce guide de script shell bash:

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 invoquons l'écho 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, donc je lance mon terminal dans Ubuntu 12.04 et j'essaye 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 vient de renvoyer la chaîne au terminal. Pourquoi ai-je obtenu des résultats différents?

JohnMerlino
la source
Notez que num n'est jamais affecté à la chaîne wc -l work.txt, mais au numéro 201.
ignis
Ressource associée: 3.5.4 Substitution de commandes dans le manuel de référence Bash .
Eliah Kagan

Réponses:

2

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

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

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

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

Et fonctionne également:

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

Pour plus d'informations, voir Différences entre les guillemets doubles "", les guillemets simples "et les astuces" ´ sur la ligne de commande?

Danatela
la source
Une idée pourquoi j'obtiens '1 sample.txt' et pas seulement le nombre '1'?
JohnMerlino
C'est ainsi que fonctionne la wccommande. Essayez cat sample.txt | wc -l.
Danatela
wc -l affiche le nombre de lignes présentes dans un fichier avec son nom de fichier.
Avinash Raj
5

Veuillez 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.

Ainsi, 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 une chaîne habituelle

Pensez à faire cela comme exemple:

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

Et maintenant, faites écho aux trois variables:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
la source
4

Si vous souhaitez capturer la sortie d'une commande dans une variable, vous devez soit utiliser des raccourcis, ``soit 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 réellement évaluée au moment de la déclaration de variable, pas lorsque vous l'écho. La commande est en fait exécutée dans le $()ou les backticks et la sortie de cette commande est enregistrée en tant que valeur de la variable.

En général, vous devez toujours utiliser $()au lieu de backticks qui sont obsolètes et uniquement autour 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 les raisons ``à éviter.

terdon
la source
1
Je suis d' accord des scripts devraient préférer $( )à ` `. Mais comme dit WAG , backquotes font nid. echo $(date -d $(echo yesterday))devient echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))devient echo `echo \`date -d \\\`echo yesterday\\\`\``. Je dis que cela ne réfute pas votre thèse mais pour la renforcer : les citations internes échappées rendent la ` `syntaxe plus puissante que ce qui est souvent admis, mais un traitement spécial \est étrange, surprenant et difficile à raisonner. Ce $( )que vous voyez est généralement ce que vous obtenez.
Eliah Kagan