Dans le script shell, nous pouvons remplacer expr $a*$b
par $(($a+$b))
.
Mais pourquoi pas simplement avec (($a+$b))
, car dans toute ressource, il est écrit que (())
est pour le calcul dentiers.
Nous utilisons donc $(())
quand il y a des variables au lieu de valeurs entières, nest-ce pas? Et que devrions-nous utiliser à la place de $(())
lorsque les variables peuvent recevoir des valeurs flottantes?
Commentaires
- Voir également unix.stackexchange.com/questions/149823/…
Réponse
-
Pour larithmétique,
expr
est archaïque. Ne lutilisez pas. * -
$((...))
et((...))
sont très similaires. Les deux ne font que des calculs dentiers. La différence est que$((...))
renvoie le résultat du calcul et((...))
ne le fait pas. Ainsi$((...))
est utile dans les instructionsecho
:$ 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
-
Si vous voulez du flottant calculs de points, utilisez
bc
ouawk
:$ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682
* En passant, expr
reste utile pour la gestion des chaînes lorsque les globes ne sont pas assez bons et quune méthode POSIX est nécessaire pour gérer les expressions régulières.
Commentaires
- Si expr est archaïque, que devrions-nous utiliser à la place de expr text: '. * '
- Si
s
est une variable shell, sa longueur est${#s}
- $ {#} signifie un nombre darguments et $ (# s} signifie un nombre de caractères dune variable, nest-ce pas?
- Oui. ' a raison.
- @Stranger De nombreuses utilisations de
expr STRING : REGEX
peuvent être écrites sous la formecase STRING in PATTERN)
.expr
nest utile que lorsque REGEX peut ' être exprimé avec des caractères génériques de shell.
Answer
expr est vieux, mais il a un usage limité auquel je peux penser. Supposons que vous souhaitiez rechercher une chaîne. Si vous voulez rester POSIX avec grep, vous devez utiliser un tube:
if echo november | grep nov then : do something fi
expr peut le faire sans tube:
if expr november : nov then : do something fi
le seul hic est que expr fonctionne avec des chaînes ancrées, donc si vous voulez faire correspondre après le début, vous devez changer le REGEXP:
if expr november : ".*ber" then : do something fi
Concernant (( ))
, cette construction nest pas POSIX , elle doit donc être évitée.
Concernant $(( ))
, il nest pas nécessaire dinclure le signe dollar:
$ fo=1 $ go=2 $ echo $((fo + go)) 3
Commentaires
- De nombreuses utilisations de
expr STRING : REGEX
peuvent être écrites sous la formecase STRING in PATTERN)
.expr
nest utile que lorsque REGEX peut ' être exprimé avec des caractères génériques de shell.
Réponse
Il semble que les programmes suivants font plus ou moins la même chose et ils ne diffèrent pas vraiment. Mais ce nest pas vrai.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s
Cest la manière correcte de mettre en œuvre cela. Lexpression s + 1 est évaluée par le shell et peut être affectée à une variable.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s
Ici, lexpression sera calculée par le programme expr, qui nest pas un shell intégré mais un programme Unix externe. Ainsi, au lieu dajouter simplement 1 et s, un programme doit être lancé et sa sortie doit être lue et écrite dans la variable. Démarrer un programme nécessite beaucoup de ressources et beaucoup de temps. Et ce programme est exécuté 1000000 fois. Le programme sera donc 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 lindicateur -e nest pas défini, le programme fonctionnera également correctement. Mais si -e est défini lorsque s = -1 et ((s = s + 1)) est calculé. Lexpression s = s + 1 prend la valeur 0 et le code de sortie de ((0)) est> 0, ce qui est interprété comme une erreur par le shell et le shell quitte le programme.
La raison de définir loption -e est que cest le moyen le plus simple de traiter les erreurs: arrêter si une erreur se produit.