Comment puis-je faire une division avec des variables dans un shell Linux?
136
Lorsque j'exécute des commandes dans mon shell comme ci-dessous, cela renvoie une expr: non-integer argumenterreur. Quelqu'un pourrait-il me l'expliquer?
$ x=20
$ y=5
$ expr x / y
expr: non-integer argument
@ShivanRaptor Bien que l'on puisse affirmer que la question est une question RTFM, c'est certainement une question de programmation shell valide. C'est aussi une question raisonnable pour quelqu'un venant de langages qui ne nécessitent pas de déréférencement (par exemple Ruby ou JavaScript). Il devrait être laissé ouvert.
Todd A. Jacobs
6
@ShivanRaptor Non, c'est sur le sujet ici. Il s'agit de programmer dans Bash. Unix / Linux sert principalement à utiliser le système, pas à programmer. Maintenant, les scripts shell couvrent la frontière entre la programmation et l'utilisation du système, donc cela pourrait être sur le sujet sur l'un ou l'autre site. S'il y avait une question sur "comment configurer le réseau", cela appartiendrait certainement à Unix / Linux. S'il s'agissait d'une question sur les raccourcis clavier interactifs dans Bash, cela y ferait également partie. Mais une question sur les scripts shell est définitivement sur le sujet ici et là.
Brian Campbell
Voir ma réponse ici, qui illustre la soustraction et la division des variables $ BASH, en utilisant un appel à Python depuis le shell (pour convertir int en float ...): stackoverflow.com/questions/8385627/…
Victoria Stuart
Réponses:
195
Ces variables sont des variables shell. Pour les étendre en tant que paramètres à un autre programme ( c'est-à-direexpr ), vous devez utiliser le $préfixe:
expr $x / $y
La raison pour laquelle il s'est plaint est parce qu'il pensait que vous essayiez d'opérer sur des caractères alphabétiques ( c'est -à- dire non entiers)
Si vous utilisez le shell Bash, vous pouvez obtenir le même résultat en utilisant la syntaxe d'expression:
Vous pouvez également utiliserecho '1 / 3' | bc -l
Eugene
19
Pourquoi ne pas utiliser let; Je trouve cela beaucoup plus facile. Voici un exemple que vous pourriez trouver utile:
start=`date +%s`# ... do something that takes a while ...
sleep 71
end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds
Un autre exemple simple - calculer le nombre de jours depuis 1970:
Le référencement des variables Bash nécessite une extension des paramètres
Le shell par défaut sur la plupart des distributions Linux est Bash. Dans Bash, les variables doivent utiliser un préfixe de signe dollar pour l' expansion des paramètres . Par exemple:
x=20
y=5
expr $x / $y
Bien sûr, Bash a également des opérateurs arithmétiques et une syntaxe d'expansion arithmétique spéciale , il n'est donc pas nécessaire d'invoquer le binaire expr comme un processus séparé. Vous pouvez laisser le shell faire tout le travail comme ceci:
Cela n'a rien à voir avec le déréférencement mais l' interpolation et exprest déconseillé en 2013.
Gilles Quenot
@sputnick Vous êtes clairement confus. N'hésitez pas à consulter un dictionnaire. Voir déréférencer et interpoler .
Todd A. Jacobs
1
Un meilleur mot se développe , mais pas de déréférencement . le déréférencement est utilisé lorsque nous utilisons des pointeurs , ce n'est pas le cas ici, ce sont juste des variables simples.
Gilles Quenot
1
@Prashant: tldp n'est pas connu pour être une bonne référence dans le monde bash.
Gilles Quenot
1
Supposons
x=50
y=5
puis
z=$((x/y))
cela fonctionnera correctement. Mais si vous souhaitez utiliser / operator dans les instructions case, il ne peut pas le résoudre.
Dans ce cas, utilisez des chaînes simples comme div ou devide ou autre chose. Voir le code
C'est faux. /fonctionne bien comme une étiquette de coque. Ce qui ne fonctionne pas, c'est d'utiliser *pour multiplier sans le citer, ce qui pourrait être ce que vous avez réellement fait; qui l' amène à remplacer efficacement tous les éléments suivants dans le cas, qui dans votre exemple est 'devide' et 'modulo'
dave_thompson_085
0
Pour obtenir les nombres après la virgule décimale, vous pouvez faire ceci: -
Réponses:
Ces variables sont des variables shell. Pour les étendre en tant que paramètres à un autre programme ( c'est-à-dire
expr
), vous devez utiliser le$
préfixe:La raison pour laquelle il s'est plaint est parce qu'il pensait que vous essayiez d'opérer sur des caractères alphabétiques ( c'est -à- dire non entiers)
Si vous utilisez le shell Bash, vous pouvez obtenir le même résultat en utilisant la syntaxe d'expression:
Ou:
la source
man bash
à l'invite (q
pour quitter)Je crois que cela a déjà été mentionné dans d'autres fils:
alors vous pouvez simplement taper:
Dans votre cas, ce sera:
ou si vous préférez, ajoutez ceci en tant que script séparé et rendez-le disponible dans $ PATH afin que vous l'ayez toujours dans votre shell local:
la source
echo '1 / 3' | bc -l
Pourquoi ne pas utiliser let; Je trouve cela beaucoup plus facile. Voici un exemple que vous pourriez trouver utile:
Un autre exemple simple - calculer le nombre de jours depuis 1970:
la source
Le référencement des variables Bash nécessite une extension des paramètres
Le shell par défaut sur la plupart des distributions Linux est Bash. Dans Bash, les variables doivent utiliser un préfixe de signe dollar pour l' expansion des paramètres . Par exemple:
Bien sûr, Bash a également des opérateurs arithmétiques et une syntaxe d'expansion arithmétique spéciale , il n'est donc pas nécessaire d'invoquer le binaire expr comme un processus séparé. Vous pouvez laisser le shell faire tout le travail comme ceci:
la source
expr
est déconseillé en 2013.Supposons
puis
cela fonctionnera correctement. Mais si vous souhaitez utiliser / operator dans les instructions case, il ne peut pas le résoudre. Dans ce cas, utilisez des chaînes simples comme div ou devide ou autre chose. Voir le code
la source
/
fonctionne bien comme une étiquette de coque. Ce qui ne fonctionne pas, c'est d'utiliser*
pour multiplier sans le citer, ce qui pourrait être ce que vous avez réellement fait; qui l' amène à remplacer efficacement tous les éléments suivants dans le cas, qui dans votre exemple est 'devide' et 'modulo'Pour obtenir les nombres après la virgule décimale, vous pouvez faire ceci: -
la source