expr
ne semble pas aimer les parenthèses (utilisées en mathématiques selon 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?
expr
ne semble pas aimer les parenthèses (utilisées en mathématiques selon 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?
Réponses:
Une autre façon d'utiliser let
bash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Remarque
Comme @ Stéphane Chazelas l'a souligné , bash
vous devez utiliser ((...))
pour effectuer des calculs arithmétiques expr
ou let
pour améliorer la lisibilité.
Pour la portabilité, utilisez $((...))
comme @Bernhard answer .
let
. Ce n'est pas plus standard ou portable que (( a = 3 * (2 + 1) ))
(les deux viennent de ksh
et ne sont disponibles qu'en ksh, bash et zsh) et il est moins lisible ou facile à citer. Utilisez a=$((3 * (2 + 1)))
pour être portable.
((a = 3 * (2 + 1) ))
, une pour la portabilité a=$((3 * (2 + 1)))
), donc ce n'est pas une note contre vous ou votre réponse mais contre le fait qu'elle soit la réponse choisie et meilleur buteur.
a=1 $[a+2]
ou a=1 b=2 $[a+b]
. Est-ce leur raison d'éviter cette syntaxe?
Vous pouvez utiliser plutôt l’expansion arithmétique.
echo "$(( 3 * ( 2 + 1 ) ))"
9
À mon avis, cela semble un peu plus agréable que d’utiliser expr
.
De man bash
Expansion arithmétique Une expansion arithmétique permet l'évaluation d'une expression arithmétique et la substitution du résultat. Le format de développement arithmétique est le suivant:
$((expression))
L'expression est traitée comme si elle se trouvait entre guillemets doubles, mais les guillemets doubles entre parenthèses ne font pas l'objet d'un traitement particulier. Tous les jetons de l'expression subissent une extension de paramètre, une extension de chaîne, une substitution de commande et une suppression de devis. Les développements arithmétiques peuvent être imbriqués.
L’évaluation est effectuée selon les règles énumérées ci-dessous sous ÉVALUATION ARITHMÉTIQUE. Si expression n'est pas valide, bash affiche un message indiquant un échec et aucune substitution n'est effectuée.
Il n'y a aucune raison d'utiliser l' expr
arithmétique dans les coques modernes.
POSIX définit l' $((...))
opérateur d'extension. Vous pouvez donc utiliser cela dans tous les shells compatibles POSIX (les sh
plus modernes, comme dash, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
a également introduit une commande let
intégrée qui est transmise au même type d'expression arithmétique, ne se développe pas en quelque chose, mais retourne un statut de sortie basé sur le fait que l'expression soit résolue ou non, comme dans expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
Cependant, comme les citations le rendent maladroit et pas très lisible (pas dans la même mesure que expr
bien sûr), ksh
introduit également une ((...))
forme alternative:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
ce 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 privilégiée si la portabilité vers d'autres shells est nécessaire, si elle expr
est utilisée uniquement pour les shells pré-POSIX de type Bourne (généralement le shell Bourne ou les premières versions du shell Almquist).
Sur le front non Bourne, il y a quelques obus avec un opérateur arithmétique intégré:
csh
/ tcsh
(réellement le premier shell Unix avec évaluation arithmétique intégrée):
@ a = 3 * (2 + 1)
akanga
(basé sur rc
)
a = $:'3 * (2 + 1)'
Comme note historique, la version originale du shell Almquist, telle que publiée sur usenet en 1989, comportait une fonction expr
intégrée (fusionnée avec test
), mais elle a été supprimée ultérieurement.
: $((a = a*2))
vous
$((...))
comme zsh, ksh93 ou yash.
expr
est une commande externe, ce n’est pas une syntaxe de shell spéciale. Par conséquent, si vous souhaitez expr
voir les caractères spéciaux du shell, vous devez les protéger de l'analyse syntaxique du shell en les citant. De plus, expr
chaque numéro et chaque opérateur doivent être passés en tant que paramètre séparé. 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 de l'utiliser expr
. Auparavant, les coquilles n'avaient pas de méthode intégrée pour effectuer des calculs, et vous deviez appeler l' expr
utilitaire à la place. Tous les shells POSIX ont l'arithmétique intégrée via la syntaxe d' expansion arithmétique .
echo "$((3 * (2 + 1)))"
La construction se $((…))
développe jusqu'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 tâches ou pour tester si une expression est 0 mais ne vous souciez pas du résultat. Cette construction existe également dans ksh et zsh mais pas dans plain 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 chaîne. Celles-ci aussi sont assimilées aux fonctionnalités des shells POSIX, à l'exception de l'une des suivantes: expr STRING : REGEXP
teste si la chaîne correspond à l'expression rationnelle spécifiée. Un shell POSIX ne peut pas le faire sans outils externes, mais bash avec [[ STRING =~ REGEXP ]]
(avec une syntaxe d'expression régulière différente - expr
est un outil classique et utilise BRE, bash utilise ERE).
À moins que vous n'utilisiez des scripts exécutés sur des systèmes vieux de 20 ans, vous n'avez pas besoin de savoir que cela a expr
déjà existé. Utilisez l'arithmétique des coques.
expr foo : '\(.\)'
fait aussi l'extraction de texte. bash
« s BASH_REMATCH
permette d' obtenir quelque chose de similaire. Il effectue également une comparaison des chaînes, ce que POSIX [
ne fait pas (bien que l'on puisse imaginer des façons d'utiliser sort
cela).
Utilisez des parenthèses avec des guillemets:
expr 3 '*' '(' 2 '+' 1 ')'
9
Les guillemets empêchent bash d’interpréter la parenthèse en tant que syntaxe bash.
expr
ligne de commande doivent être séparés par des espaces. alors; par exemple, expr 3 "*" "(2" "+" "1)"
ne fonctionnera pas . (En outre, BTW, vous n'avez probablement pas besoin de citer le +
.)
while
et [[
, ils sont la syntaxe. S'ils étaient des mots-clés, ils ne seraient pas interprétés comme tels dans les arguments de commande. Vous avez besoin de guillemets pour que bash ne les analyse pas mais affiche un littéral de chaîne.