259 votes

bash - soustraire 2 variables

J'ai le script ci-dessous pour soustraire les comptes de fichiers entre 2 répertoires mais la COUNT= ne fonctionne pas, quelle est la syntaxe correcte ?

 #!/usr/bin/env bash

FIRSTV=`ls -1 | wc -l`
cd ..
SECONDV=`ls -1 | wc -l`
COUNT=expr $FIRSTV-$SECONDV
echo $COUNT

1 votes

427voto

anubhava Points 172509

Essayez cette syntaxe bash au lieu d'essayer d'utiliser un programme externe expr :

count=$((FIRSTV-SECONDV))

La syntaxe correcte d'utilisation d'expr est :

count=$(expr $FIRSTV - $SECONDV)

mais gardez à l'esprit que l'utilisation de expr sera plus lente que la syntaxe bash interne que je vous ai fournie ci-dessus.

4 votes

Cette forme est beaucoup plus rapide que l'utilisation du programme externe expr.

0 votes

Cela fonctionne sans les backticks, mais puis-je savoir pourquoi ? +1 pour la réponse

3 votes

Merci. Backtick est une ancienne syntaxe shell. BASH prend en charge la nouvelle $(command) syntaxe pour la substitution de commandes. De plus, depuis que BASH supporte les opérations arithmétiques en $(( ... )) il est préférable de ne pas utiliser d'utilitaire externe expr

249voto

Aaron McDaid Points 7761

Vous avez juste besoin d'un peu d'espace supplémentaire autour du signe moins, et des backticks :

COUNT=`expr $FIRSTV - $SECONDV`

3 votes

Cette réponse fonctionne également sous Posix sh coquille. Pour des raisons de portabilité, vous pouvez utiliser cette réponse.

1 votes

Il est intéressant de noter que, selon Shellcheck, expr est un codemell en raison de son caractère désuet et difficile à utiliser : github.com/koalaman/shellcheck/wiki/SC2003

0 votes

Je suis d'accord ; la réponse d'Anubhava devrait être la réponse acceptée. expr n'a de sens que si vous avez besoin d'une compatibilité remontant aux âges sombres où Solaris sh était populaire et que HP-UX et AIX existaient encore. POSIX sh aussi supporte les expressions arithmétiques depuis de nombreuses années maintenant.

31voto

paxdiablo Points 341644

Vous pouvez utiliser :

((count = FIRSTV - SECONDV))

pour éviter d'invoquer un processus séparé, comme dans la transcription suivante :

pax:~$ FIRSTV=7
pax:~$ SECONDV=2
pax:~$ ((count = FIRSTV - SECONDV))
pax:~$ echo $count
5

17voto

Pureferret Points 747

C'est ainsi que je fais toujours les maths dans bash :

count=$(echo "$FIRSTV - $SECONDV"|bc)
echo $count

5 votes

Qui n'est nécessaire que si l'on a affaire à des nombres à virgule flottante.

4 votes

Je m'en rends compte, mais je préfère prendre l'habitude d'attraper ces cas avec un |bc commande de type que de la manquer une ou deux fois. Comme on dit, chaque personne est différente.

1 votes

@glenn jackman mais c'est ce que je cherchais sans même savoir que mes maths décimales étaient des "floating point numbers". Aucune autre réponse n'a fonctionné pour moi, sauf celle-ci !

13voto

Karoly Horvath Points 45145

L'espace blanc est important, expr attend ses opérandes et opérateurs comme des arguments séparés. Vous devez également capturer la sortie. Comme ceci :

COUNT=$(expr $FIRSTV - $SECONDV)

mais il est plus courant d'utiliser l'expansion arithmétique intégrée :

COUNT=$((FIRSTV - SECONDV))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X