Comparaison dentiers: expression arithmétique ou expression conditionnelle

Dans Bash, deux entiers peuvent être comparés à laide dune expression conditionnelle

arg1 OP arg2

OP est lun des -eq, -ne, -lt, -le, -gt ou -ge. Ces opérateurs binaires arithmétiques renvoient true si arg1 est égal, différent de, inférieur à, inférieur ou égal à, supérieur ou supérieur ou égal à arg2 , respectivement. Arg1 et arg2 peuvent être des entiers positifs ou négatifs.

ou une expression arithmétique:

<= >= < > comparaison

== != égalité et inégalité

Pourquoi avons-nous deux manières différentes de comparer deux entiers? Quand utiliser laquelle?

Par exemple, [[ 3 -lt 2 ]] utilise une expression conditionnelle et (( 3 < 2 )) utilise une expression arithmétique. Les deux renvoient 0 lorsque la comparaison est vraie

Lors de la comparaison de deux entiers, ces deux méthodes peuvent-elles toujours être utilisées de manière interchangeable? Si oui, pourquoi Bash a-t-il deux méthodes plutôt quune?

Commentaires

  • = != < <= > >= compare chaînes . 1 -eq 01 mais 1 != 01 et 8 -lt 42 mais 8 > 42
  • Ils sont surchargés dans les expressions arithmétiques.
  • vous ‘ devrez rechercher dans les changelogs de bash pour savoir quand chaque fonctionnalité était ajoutée. Je soupçonne que les expressions arithmétiques ont été ajoutées beaucoup plus tard que la commande de test.
  • Je ne demande pas de comparer des chaînes. @muru.

Réponse

Oui, nous avons deux façons différentes de comparer deux entiers.

Il semble que ces faits ne soient pas largement acceptés dans ce forum:

  1. Dans lidiome [ ] les opérateurs de comparaison arithmétique sont -eq, -ne, -lt, -le, -gt et -ge.

    Comme ils sont également à lintérieur dune commande de test et à lintérieur dun [[ ]].

    Oui dans ces expressions idiomatiques, =, <, etc. opérateurs de chaîne.

  2. Dans lidiome (( )) les opérateurs de comparaison arithmétique sont == , !=, <, <=, >, et >=.

    Non, ce nest pas un « Arithme etic expansion « (qui commence par un $) comme $(( )). Elle est définie comme une «commande composée» dans man bash.

    Oui, elle suit les mêmes règles (en interne) de «lexpansion arithmétique» mais na pas de sortie, seulement une valeur de sortie. Il pourrait être utilisé comme ceci:

if (( 2 > 1 )); then ... 

Pourquoi avons-nous deux façons différentes de comparer deux entiers?

Je suppose que ce dernier (( )) a été développé comme un moyen plus simple deffectuer des tests arithmétiques. Cest presque le même que le $(( )) mais na simplement pas de sortie.

Pourquoi deux? Eh bien, la même chose que la raison pour laquelle nous avons deux printf (externes et intégrés) ou quatre tests (externes test, intégrés test, [ et [[). Cest ainsi que les coquilles se développent, améliorant une zone en un an, une autre lannée suivante.

Quand utiliser laquelle?

Cest une question très difficile car il ne devrait y avoir aucune différence effective. Bien sûr, il existe des différences dans la manière dont un [ ] fonctionne et un (( )) fonctionnent en interne, mais: quel est le meilleur moyen de comparer deux entiers? Nimporte lequel !.

Lors de la comparaison de deux entiers, ces deux méthodes peuvent-elles toujours être utilisées de manière interchangeable?

Pour deux nombres, je suis obligé de dire oui.
Mais pour les variables, les extensions , opérations mathématiques il peut y avoir des différences clés qui devraient favoriser lun ou lautre. Je ne peux pas dire que les deux sont absolument égaux. Dune part, le (( )) pourrait effectuer plusieurs opérations mathématiques dans lordre:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi 

Si oui, pourquoi Bash a-t-il deux méthodes plutôt quune?

Si les deux sont utiles, pourquoi pas ?.

Commentaires

  • = est une affectation et == est une comparaison dans les extensions arithmétiques. La question le cite correctement. Mais la réponse est fausse.
  • De plus, ( nest pas un mot réservé dans bash, il nest donc pas nécessaire de mettre des espaces autour de ((, comme opposé à [ ou [[

Réponse

Historiquement, la commande test existait en premier (au moins aussi loin que Unix septième édition en 1979). Il a utilisé les opérateurs = et != pour comparer des chaînes, et -eq, -ne, -lt, etc. pour comparer des nombres. Par exemple, test 0 = 00 est faux, mais test 0 -eq 00 est vrai. Je ne sais pas pourquoi cette syntaxe a été choisie, mais cela a peut-être été pour éviter dutiliser < et >, que le shell aurait analysé comme des opérateurs de redirection. La commande test a obtenu une autre syntaxe quelques années plus tard: [ … ] équivaut à test ….

La [[ … ]] syntaxe conditionnelle, dans laquelle < et > peut être utilisé comme opérateur sans guillemets, a été ajouté plus tard, dans ksh. Il a gardé la compatibilité descendante avec [ … ], donc il a utilisé les mêmes opérateurs, mais a ajouté < et > pour comparer des chaînes (par exemple, [[ 9 > 10 ]] mais [[ 9 -lt 10 ]]). Pour plus dinformations, voir Utilisation dun crochet simple ou double – bash

Les expressions arithmétiques sont également arrivées plus tard que le test commande,

dans le shell Korn , à un moment donné dans les années 1980. Ils ont suivi la syntaxe du langage C, qui était très populaire dans les cercles Unix. Ainsi, ils ont utilisé les opérateurs C « s:==pour légalité,<=pour inférieur ou égal, etc.

Unix Seventh Edition navait pas dexpressions arithmétiques, mais il avait la commande expr , qui implémentait également une Syntaxe de type C pour les opérations sur les entiers, y compris ses opérateurs de comparaison. Dans un script shell, les caractères < et > devaient être entre guillemets pour les protéger du shell, par exemple if expr 1 \< 2; … équivaut à if test 1 -lt 2; …. Lajout dexpressions arithmétiques au shell a rendu la plupart des utilisations de expr obsolètes, donc ce nest « pas bien connu aujourdhui.

Dans un script sh, vous » d utilise généralement des expressions arithmétiques pour calculer une valeur entière et [ … ] pour comparer des entiers.

if [ "$((x + y))" -lt "$z" ]; then … 

Dans un ksh , bash ou zsh, vous pouvez utiliser ((…)) pour les deux.

if ((x + y < z)); then … 

Le [[ … ]] est utile si vous souhaitez utiliser des conditions impliquant des choses autres que des entiers.

Réponse

Selon la page de manuel de test, = et! = sont utilisées pour les comparaisons de chaînes tandis que les expressions -eq, -gt, -lt, -ge, -le et -ne sont des comparaisons dentiers. Jai toujours suivi cette convention lors de lécriture de scripts shell et cela fonctionne toujours. Sachez que si vous avez des variables dans lexpression, vous devrez peut-être citer les variables dune manière ou dune autre pour éviter de faire une comparaison nulle.

Sur le papier, nous faisons des comparaisons chaîne / nombre sans trop réfléchir. Un ordinateur par contre ne sait pas si 987 est un nombre ou une chaîne de caractères. Vous avez besoin des différents opérateurs pour dire à lordinateur ce quil faut faire pour obtenir le bon résultat. Il y a quelques informations supplémentaires ici qui expliquent une partie de lhistorique. Essentiellement, les variables ne sont pas typées et sont restées ainsi pour la compatibilité historique.

Commentaires

  • Dans mon message, = et != sont des opérateurs arithmétiques, tandis que la page de manuel de test naffiche que les opérateurs dexpression conditionnelle.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *