expr
ne semble pas aimer la parenthèse (utilisée en mathématiques pour la priorité explicite de l'opérateur):
expr 3 * (2 + 1) bash: syntax error near unexpected token `('
Comment exprimer la priorité de l'opérateur dans bash?
Une autre façon d'utiliser let
bash embedded:
$ let a="3 * (2 + 1)" $ printf '%s\n' "$a" 9
Remarque
Comme @ Stéphane Chazelas l'a souligné , dans bash
vous devriez utiliser ((...))
pour faire de l'arithmétique sur expr
ou let
lisibilité.
Pour la portabilité, utilisez $((...))
comme réponse @Bernhard .
Vous pouvez utiliser l'expansion arithmétique à la place.
echo "$(( 3 * ( 2 + 1 ) ))" 9
À mon avis personnel, cela semble un peu plus agréable que d'utiliser expr
.
De l' man bash
Expansion arithmétique L'expansion arithmétique permet l'évaluation d'une expression arithmétique et la substitution du résultat. Le format de l'expansion arithmétique est le suivant:
$((expression))
L'expression est traitée comme si elle était entre guillemets doubles, mais une double citation à l'intérieur des parenthèses n'est pas traitée spécialement. Tous les jetons de l'expression subissent une expansion de paramètre, une extension de string, une substitution de command et une suppression de devis. Les expansions arithmétiques peuvent être nestedes.
L'évaluation est effectuée selon les règles listées ci-dessous sous ARITHMETIC EVALUATION. Si l'expression n'est pas valide, bash imprime un message indiquant l'échec et aucune substitution ne se produit.
Il n'y a aucune raison d'utiliser expr
pour l'arithmétique dans les coquilles modernes.
POSIX définit l'opérateur de développement $((...))
. Vous pouvez donc utiliser cela dans tous les shells compatibles POSIX (le sh
de tous les modernes Unix-aime, tiret, bash, yash, mksh, zsh, posh, ksh …).
a=$(( 3 * (2 + 1) )) a=$((3*(2+1)))
ksh
également introduit un let
builtin qui est passé le même type d'expression arithmétique, ne se développe pas en quelque chose mais renvoie un statut de sortie basé sur la résolution de 0 ou non de l'expression, comme dans expr
:
if let 'a = 3 * (2 + 1)'; then echo "$a is non-zero" fi
Cependant, comme la citation la rend maladroite et peu lisible (pas dans la même mesure expr
), ksh
également introduit une forme alternative ((...))
:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then echo "$a is non-zero and 3 > 1" fi ((a+=2))
qui est beaucoup plus lisible et devrait être utilisé à la place.
let
et ((...))
ne sont disponibles que dans ksh
, zsh
et bash
. La syntaxe $((...))
doit être préférée si la portabilité vers d'autres shells est nécessaire, expr
n'est nécessaire que pour les shells Bourne-like POSIX (généralement le shell Bourne ou les premières versions du shell Almquist).
Sur le front non-Bourne, il y a quelques shells avec opérateur arithmétique embedded:
csh
/ tcsh
(en fait le premier shell Unix avec évaluation arithmétique embedded):
@ a = 3 * (2 + 1)
akanga
(basé sur rc
)
a = $:'3 * (2 + 1)'
comme une note d'histoire, la version originale de la coquille Almquist, comme posté sur usenet en 1989 avait un expr
builtin (effectivement fusionné avec le test
), mais il a été retiré plus tard.
Utilisez des parenthèses avec des guillemets:
expr 3 '*' '(' 2 '+' 1 ')' 9
Les citations empêchent bash d'interpréter la parenthèse comme syntaxe bash.
expr
est une command externe, ce n'est pas une syntaxe shell spéciale. Par conséquent, si vous souhaitez que expr
des caractères spéciaux shell, vous devez les protéger de l'parsing des interpréteurs de commands en les citant. En outre, expr
besoin de chaque numéro et de chaque opérateur comme paramètre distinct. Ainsi:
expr 3 \* \( 2 + 1 \)
Sauf si vous travaillez sur un système unix antique des années 1970 ou 1980, il y a très peu de raisons d'utiliser expr
. Dans les time anciens, les shells n'avaient pas de méthode embeddede pour effectuer l'arithmétique, et vous deviez appeler l'utilitaire expr
place. Tous les obus POSIX ont une arithmétique embeddede via la syntaxe d' expansion arithmétique .
echo "$((3 * (2 + 1)))"
La construction $((…))
s'étend au résultat de l'expression arithmétique (écrite en décimal). Bash, comme la plupart des shells, ne supporte que l'arithmétique entière modulo 2 64 (ou modulo 2 32 pour les anciennes versions de bash et d'autres shells sur les machines 32 bits).
Bash offre une syntaxe de commodité supplémentaire lorsque vous souhaitez effectuer des affectations ou pour tester si une expression est 0 mais ne vous souciez pas du résultat. Cette construction existe aussi dans ksh et zsh mais pas dans plaine sh.
((x = 3 * (2+1))) echo "$x" if ((x > 3)); then …
En plus de l'arithmétique entière, expr
offre quelques fonctions de manipulation de string. Ceux-ci sont également englobés par les fonctionnalités des shells POSIX, à l'exception d'un seul: expr STRING : REGEXP
teste si la string correspond à l'expression rationnelle spécifiée. Un shell POSIX ne peut pas faire cela sans outils externes, mais bash peut avec [[ STRING =~ REGEXP ]]
(avec une syntaxe regexp différente – expr
est un outil classique et utilise BRE, bash utilise ERE).
Sauf si vous maintenez des scripts qui fonctionnent sur des systèmes de 20 ans, vous n'avez pas besoin de savoir que l' expr
existe. Utilisez l'arithmétique shell.
Si vous avez bc ..
echo '3 * (2 + 1)'|bc 9