5 votes

Comparer des numéros de version à plusieurs chiffres en bash

J'essaie d'écrire un script qui recherche la version de l'application puis renvoie la valeur. Mon problème est que la valeur est longue de trois à quatre entiers (exemple 4.3.2).

J'ai cherché pendant un certain temps et je n'ai pas trouvé de syntaxe permettant d'utiliser != ou -ge pour tout ce qui est supérieur à un nombre comportant des points. Je me demande si quelqu'un a une meilleure solution ou si je vais continuer à en ajouter à chaque nouvelle version.

Ce que je veux

else if [ $version1 -ge "9.0.8" ]; then

Comment c'est écrit maintenant

vercheck=`mdls -name kMDItemVersion /Applications/iMovie.app`
version=`echo ${vercheck:17}`
version1=`echo ${version:1:5}`

[...]

else if [ $version1 = "9.0.8" ]; [ $version1 = "9.1.1" ]; then
    echo "You already have this version or a higher version installed"
    exit 0

4voto

moodforaday Points 2633

Je crois que je l'ai légèrement adapté de http://bashscripts.org/forum/viewtopic.php?f=16&t=1248 . Je l'aime parce qu'il est assez compact et lisible.

Ceci est optionnel, mais souhaitable IMO :

if [ "$#" != "2" ]
then
    echo "$0 requires exactly two arguments."
    exit 2
fi

Voici la viande :

J'utilise toujours $1 pour "la version installée localement" et $2 pour " la version à laquelle je compare ", donc si cela me laisse avec $? = 1 Je dois mettre à jour, sinon je suis à jour (ou même en avance) :

function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

if [ $(version $1) -gt $(version $2) ]; then
    echo "$1 is newer than $2"
    exit 0
elif [ $(version $1) -lt $(version $2) ]; then
    echo "$1 is older than $2"
    exit 1
else
    echo "$1 is identical to $2"
    exit 0
fi

Si tout ce qui vous importe est de savoir si $1 était à jour (c'est-à-dire égal ou supérieur à $2 ), vous pourriez le rendre encore plus simple :

if [ $(version $1) -ge $(version $2) ]; then
    echo "No Newer Version Available"
    exit 0
fi

Tout code en dessous de cela ne sera exécuté que si une version plus récente est disponible. Sinon, le script se terminera proprement à ce moment-là.

p.s. : Je fais ça dans /bin/zsh et non /bin/bash mais je n'ai pas pensez à ça fait une différence dans ce cas.

0voto

Ryan Spears Points 1524

En fait, la comparaison des numéros de version est assez simple (du moins tant qu'ils sont strictement numériques) car ils sont structurés hiérarchiquement de gauche à droite. Une comparaison séquentielle dans ce même ordre donnera un résultat clair.

Les éléments suivants bash La fonction renverra 0 (vrai) si deux numéros de version sont pas égal , 1 (faux) s'ils le sont, pour autant que les variables $version_1 y $version_2 tous deux ne contiennent qu'un nombre arbitraire de groupes de chiffres séparés par des points :

function versions_not_equal {
    while [[ $version_1 != "0" || $version_2 != "0" ]]; do
        (( ${version_1%%.*} != ${version_2%%.*} )) && return 0
        [[ ${version_1} =~ "." ]] && version_1="${version_1#*.}" || version_1=0
        [[ ${version_2} =~ "." ]] && version_2="${version_2#*.}" || version_2=0
    done
    false
}

La mise en œuvre d'autres comparaisons, comme supérieur ou égal est aussi simple que de changer l'opérateur de comparaison de l'évaluation arithmétique (c.-à-d. (( ${version_1%%.*} >= "${version_2%%.*}" )) ).

0voto

lyonsinbeta Points 101

Je peux vous donner un long exemple de "si la version vérifiée est entre min et max" et vous pouvez l'optimiser pour vos besoins en changeant la tête -1/la queue -1 et en coupant 1 variable :

min_ver="a-1.1.1"
max_ver="a-9.1.1"
check_ver="a-2.2.9"
if [ "$( echo -e "${min_ver}\\n${max_ver}\\n${check_ver}" | sort --sort=version | head -2 | tail -1)" == ${check_ver} ]
then
  echo YES - apply  ${check_ver}
fi

0voto

mato Points 160

Voici une autre solution qui :

  • n'exécute aucune commande externe, à l'exception de tr
  • n'a aucune restriction sur le nombre de parties dans la chaîne de version
  • peut comparer des chaînes de versions avec un nombre différent de parties

Notez que c'est du code Bash utilisant des variables de type tableau.

compare_versions()
{
    local v1=( $(echo "$1" | tr '.' ' ') )
    local v2=( $(echo "$2" | tr '.' ' ') )
    local len="$(max "${#v1[*]}" "${#v2[*]}")"
    for ((i=0; i<len; i++))
    do
        [ "${v1[i]:-0}" -gt "${v2[i]:-0}" ] && return 1
        [ "${v1[i]:-0}" -lt "${v2[i]:-0}" ] && return 2
    done
    return 0
}

La fonction renvoie :

  • 0 si les versions sont égales (btw : 1.2 == 1.2.0)
  • 1 si la 1ère version est plus grande / plus récente
  • 2 si la 2e version est plus grande / plus récente

Cependant, la fonction #1 -- elle nécessite une fonction supplémentaire (mais la fonction min est tout à fait utilisable pour avoir de toute façon) :

min()
{
    local m="$1"
    for n in "$@"
    do
        [ "$n" -lt "$m" ] && m="$n"
    done
    echo "$m"
}

Cependant, le numéro 2 ne permet pas de comparer des chaînes de versions avec des parties alphanumériques (bien que cela ne soit pas difficile à ajouter, en fait).

0voto

Ivan Dyachenko Points 101

Vous pouvez utiliser version CLI pour vérifier les contraintes de la version

$ version ">=1.0, <2.0" "1.7"
$ go version | version ">=1.9"

Exemple de Bash script :

#!/bin/bash

if `version -b ">=9.0.0" "$(gcc --version)"`; then
  echo "gcc version satisfies constraints >=9.0.0"
else
  echo "gcc version doesn't satisfies constraints >=9.0.0"
fi

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X