web-dev-qa-db-fra.com

En utilisant EXPR, $ (()), (())

Dans le script shell, nous pouvons remplacer expr $a*$b Avec $(($a+$b)).

Mais pourquoi pas seulement avec (($a+$b)), Car dans toute ressource, il est écrit que (()) Est destiné au calcul entier.

Nous utilisons donc $(()) quand il y a des variables au lieu de valeurs entières, n'est-ce pas? Et que devons-nous utiliser au lieu de $(()) lorsque les variables peuvent recevoir des valeurs de flotteur?

7
Stranger
  1. Pour l'arithmétique, expr est archaïque. Ne l'utilisez pas. *

  2. $((...)) et ((...)) sont très similaires. Les deux ne font que des calculs entier. La différence est que $((...)) renvoie le résultat du calcul et ((...)) Ne le fait pas. Ainsi, $((...)) est utile dans echo déclarations:

    $ a=2; b=3; echo $((a*b))
    6
    

    ((...)) Est utile lorsque vous souhaitez affecter une variable ou définir un code de sortie:

    $ a=3; b=3; ((a==b)) && echo yes
    yes
    
  3. Si vous souhaitez des calculs de points flottants, utilisez bc ou awk:

    $ echo '4.7/3.14' | bc -l
    1.49681528662420382165
    
    $ awk 'BEGIN{print 4.7/3.14}'
    1.49682
    

* En tant que de côté, expr reste utile pour la manipulation des chaînes lorsque les globs ne sont pas suffisamment bons et une méthode POSIX est nécessaire pour gérer les expressions régulières.

14
John1024

expr est vieux, mais il a une utilisation limitée que je peux penser. Dis que vous voulez rechercher une chaîne. Si vous souhaitez rester posix avec Grep, vous devez utiliser un tuyau:

if echo november | grep nov 
then
  : do something
fi

expr peut faire cela sans tuyau:

if expr november : nov
then
  : do something
fi

la seule prise est EXPR fonctionne avec des chaînes ancrées, donc si vous souhaitez correspondre après le début, vous devez modifier le REGEXP:

if expr november : '.*ber'
then
  : do something
fi

En ce qui concerne (( )), Cette construction n'est pas POSIX , doit donc être évitée.

En ce qui concerne $(( )), vous n'avez pas à inclure le signe du dollar:

$ fo=1
$ go=2
$ echo $((fo + go))
3
2
Steven Penny

Il semble que les programmes suivants font plus ou moins la même chose et ils ne diffèrent pas vraiment. Mais ce n'est pas vrai.

#!/bin/bash 
s=-1000
for (( i=0; i<1000000; i++ )), do
    s=$((s+1))
echo $s

C'est la bonne façon de la mettre en œuvre. L'expression s + 1 est évaluée par la coque et peut être attribuée à une variable.

#!/bin/bash
s=-1000
for (( i=0; i<1000000; i++ )), do
    s=`expr $s+1`
echo $s

Ici, l'expression sera calculée par le programme Expr, qui n'est pas une coquille intégrée mais un programme UNIX externe. Ainsi, au lieu d'ajouter simplement 1 et S, un programme doit être démarré et sa sortie doit être lu et écrit à la variable. Démarrer un programme a besoin de nombreuses ressources et beaucoup de temps. Et ce programme est exécuté 1000000 fois. Donc, le programme sera beaucoup plus lent que le précédent. Néanmoins, le code fonctionne correctement.

#!/bin/bash -e
s=-1000
for (( i=0; i<1000000; i++ )), do
    ((s=s+1))
echo $s

Si le drapeau n'est pas défini, le programme fonctionnera également correctement. Mais si -E -E est défini lorsque S = -1 et (S = S + 1)) est calculé. L'expression S = S + 1 évalue à 0 et le code de sortie de ((0)) est> 0 qui est interprété comme une erreur par la coque et la coque quitte le programme.

La raison de définir le drapeau -E est que c'est le moyen le plus simple de traitement des erreurs: arrêtez-vous si une erreur OCRS.

0
miracle173