Parenthèse en expr arithmétique: 3 * (2 + 1)

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