Forum Programmation.shell Comparer deux numéros de versions

Posté par  .
Étiquettes : aucune
0
28
déc.
2006
Bonjour,
je dispose de deux variables VERSION_CLIENT et VERSION_APPLI contenant des numéros de versions.
Je dois comparer ces numéros de versions et cela me pose problème.
En effet, la comparaison bash se fait selon l'ordre lexicographique et mes versions sont de la forme:
x.yz
ou x et y sont des entiers (en gros le majeur et le mineur)
et z est une lettre (release)

Donc bon, j'avais bien une solution à la base du style:

[code]
if [[ $VERSION_CLIENT > $VERSION_APPLI ]]
then
echo "le bon traitement ici"
fi
[/code]

Oui, ça va pas chercher bien loin et effectivement, c'est loin de marcher pour tous les cas...

En effet, si le majeur (le x) devient supérieur à 9, on entre dans des problème lors de la comparaison. Si on compare 9.2a et 10.2a, la comparaison lexicographique va voir que 9 est plus grand que 1 et ça va donc foirer.
L'idée, c'est de découper le tout selon 3 variable et de les comparer une à une. Donc en gros, avant le '.', ça serait la variable majeure, ensuite avant que une lettre apparaisse (je sais, normalement elle est en deuxième position, après le point mais autant que ça soit évolutif), ça serait la variable mineure, et enfin la lettre serait la release.

J'ai voulu utiliser awk et sed pour faire ça, mais j'arrive pas du tout. Je vois pas comment les utiliser et je commence à devenir fou, alors que ça me semble être pas trop trop chaud. Mais je débute vraiment avec ces deux outils, si quelqu'un pouvait me donner une piste...
Merci d'avance!
  • # Re

    Posté par  . Évalué à 0.

    Une solution est de virer la lettre servant à identifier la release, et alors, tu peux utiliser la comparaison arithmétique ((( ))) de bash:


    [binarym@senso-rezo]:~% a=4.100 b=3.10; if (( $a > $b )); then echo plop ; fi
    plop
    [binarym@senso-rezo]:~% a=4.100 b=3.10; if (( $a < $b )); then echo plop ; fi
    [binarym@senso-rezo]:~%
    • [^] # Re: Re

      Posté par  . Évalué à 0.

      Ben oui mais justement, moi je dois garder la lettre... en plus, ce que tu utilises est la comparaison de chaine de bash, et non la comparaison arithmétique qui s'utilise avec -gt par exemple si je ne m'abuse.
      • [^] # Re: Re

        Posté par  . Évalué à 1.

        Tu compare algorithmiquement (?!?) et si c'est egale, tu fais une comparaison lexicographique (qui marchera forcement puisque x et y seront egaux.
  • # re

    Posté par  . Évalué à 4.

    En bash, avec VERSION=2.3a :
    • Le chaîne avant le point : VERSION=2.3a; echo ${VERSION%%.*}
    • Le nombre de caractères composant la variable : VERSION=2.3a; echo ${#VERSION}
    • Le dernier caractère de la chaîne : VERSION=2.3a; ((nb=${#VERSION}-1)); echo ${VERSION:$nb}
    • La chaîne après le point : VERSION=2.3a; echo ${VERSION##*.}
    • Le nombre après le point : VERSION=2.30a; chaine=${VERSION##*.}; ((nb=${#chaine}-1)); echo ${chaine:0:$nb}
    • Comparer 2 nombres contenus dans des variables : var1=7; var2=4; if [ $var1 -gt $var2 ]; then echo "var1 plus grand que var2"; fi
    Avec tout ceci tu devrais t'en sortir.
    • [^] # Re: re

      Posté par  . Évalué à 2.

      Merci beaucoup, je vais regarder tout ça!
  • # Solution

    Posté par  . Évalué à 1.

    Bon, je suis arrivé à une solution, et pourtant, ça daube à l'exécution, et je vois vraiment pas pourquoi. Voici mon code de test:

    VERSION_CLIENT="9.2a"
    VERSION_APPLI="8.2b"
    SUFFIX_CLIENT=$(echo $VERSION_CLIENT | awk -F . '{ print $2 }')
    PREFIX_CLIENT=$(echo $VERSION_CLIENT | awk -F . '{ print $1 }')
    MINOR_CLIENT=$(echo $SUFFIX_CLIENT | sed -e 's/[a-z]//' )
    RELEASE_CLIENT=$(echo $SUFFIX_CLIENT | sed -e 's/[0-9]//' )


    SUFFIX_APPLI=$(echo $VERSION_APPLI | awk -F . '{ print $2 }')
    PREFIX_appli=$(echo $VERSION_APPLI | awk -F . '{ print $1 }')
    MINOR_APPLI=$(echo $SUFFIX_APPLI | sed -e 's/[a-z]//' )
    RELEASE_APPLI=$(echo $SUFFIX_APPLI | sed -e 's/[0-9]//' )

    #On compare d'abord le prefixe en utilisant la comparaison arithmétique
    if [ $PREFIX_APPLI -gt $PREFIX_CLIENT ]
    then
    echo "PREFIX APPLI PLUS GRAND"
    if [ $MINOR_APPLI -gt $MINOR_CLIENT ]
    then
    echo "MINOR APPLI PLUS GRAND"
    if [[ $RELEASE_APPLI > $RELEASE_CLIENT ]]
    then
    echo "RELEASE APPLI PLUS GRAND"
    fi
    fi
    fi


    Et à l'exécution, je me prends un:

    [: -gt: unary operator expected


    J'ai vraiment aucune idée... je vois pas ce qui est mal fait, ma découpe fonctionne pourtant...
    PS: Je sais, ma variable release ferait mieux de s'appeler revision mais bon, de là ne vient pas le problème.
    • [^] # Re: Solution

      Posté par  . Évalué à 2.

      Tu as mis appli en minuscule dans PREFIX_APPLI ligne 10
      • [^] # Re: Solution

        Posté par  . Évalué à 2.

        Oui, merci, j'avoue que mon erreur est honteuse snif...
        Pour me faire pardonner, voilà un truc qui marche pour déterminer si deux numéros de versions sont différents et de lancer un traitement le cas échéant.


        # Pour comparer les versions, il ne faut pas utiliser la comparaison lexicographique directement
        # car elle entraine des resultats faux dans certains cas
        # On sépare donc un numéro de version en trois - Le prefixe (nombre entier), le mineur (chiffre), et la release (lettre)
        # La variable COPY_SCRIPT indique si il est necessaire de copier les
        # scripts de l'application vers le client

        COPY_SCRIPT="0"
        VERSION_CLIENT=4.2
        VERSION_APPLI=4.1a
        SUFFIX_CLIENT=$(echo $VERSION_CLIENT | awk -F . '{ print $2 }')
        PREFIX_CLIENT=$(echo $VERSION_CLIENT | awk -F . '{ print $1 }')
        MINOR_CLIENT=$(echo $SUFFIX_CLIENT | sed -e 's/[a-z]//' )
        RELEASE_CLIENT=$(echo $SUFFIX_CLIENT | sed -e 's/[0-9]//' )


        SUFFIX_APPLI=$(echo $VERSION_APPLI | awk -F . '{ print $2 }')
        PREFIX_APPLI=$(echo $VERSION_APPLI | awk -F . '{ print $1 }')
        MINOR_APPLI=$(echo $SUFFIX_APPLI | sed -e 's/[a-z]//' )
        RELEASE_APPLI=$(echo $SUFFIX_APPLI | sed -e 's/[0-9]//' )



        # Si les version de l'application et du client sont différentes
        if [ $VERSION_APPLI != $VERSION_CLIENT ]
        then
        # La migration automatique a été activée
        if [ $AUTO_MIGRATION = "true" ]
        then
        #On compare d'abord le prefixe en utilisant la comparaison arithmétique
        if [ $PREFIX_APPLI -ge $PREFIX_CLIENT ]
        then
        if [ $PREFIX_APPLI -eq $PREFIX_CLIENT ]
        then
        echo "PREFIX APPLI EGAL"
        if [ $MINOR_APPLI -ge $MINOR_CLIENT ]
        then
        if [ $MINOR_APPLI -eq $MINOR_CLIENT ]
        then
        echo "MINOR APPLI EGAL"
        if [[ $RELEASE_APPLI > $RELEASE_CLIENT ]]
        then
        COPY_SCRIPT="1"
        fi
        else
        echo "MINOR APPLI PLUS GRAND"
        COPY_SCRIPT = "1"
        fi
        fi
        else
        echo "PREFIX APPLI PLUS GRAND"
        COPY_SCRIPT="1"
        fi
        fi

        if [ $COPY_SCRIPT == "1" ]
        then
        echo "LE TRAITEMENT A LANCER"
        fi

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.