Confronta i numeri di versione a più cifre in bash

4

Cercando di scrivere uno script che cerca la versione dell'applicazione, restituisce il valore. Il mio problema è che il valore è da tre a quattro interger lunghi (esempio 4.3.2).

Ho cercato per un po 'e non riesco a trovare alcuna sintassi che ti permetta di usare un! = o -ge per qualcosa di più alto di un numero con periodi al suo interno. Mi chiedo solo se qualcuno ha un modo migliore o continuerò ad aggiungere per ogni versione.

Cosa voglio

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

Come è stato scritto ora

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
    
posta balooga1 01.03.2013 - 17:52
fonte

5 risposte

1

Credo di aver leggermente adattato questo da link . Mi piace perché è abbastanza compatto e leggibile.

Questo è opzionale, ma IMO desiderabile:

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

Ecco la carne:

Uso sempre $1 per "la versione installata localmente" e $2 per "la versione con cui sto confrontando" quindi se questo mi lascia con $? = 1 devo aggiornare, altrimenti sono pronto -data (o anche avanti):

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

Se tutto ciò che ti interessava era se $1 fosse aggiornato (cioè uguale o maggiore di $2 ) potresti renderlo ancora più semplice:

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

Qualsiasi codice qui sotto che verrà eseguito solo se è disponibile una versione più recente. Altrimenti lo script uscirà pulito a quel punto.

p.s .: Lo faccio in / bin / zsh non / bin / bash ma non penso fa la differenza in questo caso.

    
risposta data 06.03.2014 - 21:36
fonte
0

In realtà, confrontare i numeri di versione è piuttosto semplice (almeno finché sono strettamente numerici) poiché sono strutturati gerarchicamente da sinistra a destra. Un confronto sequenziale nello stesso ordine produrrà un risultato chiaro.

La seguente funzione bash restituirà 0 (vero) se due numeri di versione sono non uguali , 1 (false) se lo sono, purché le variabili $version_1 e $version_2 contengono entrambi un numero arbitrario di gruppi di cifre separati da punti:

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
}

Implementare altri confronti, come maggiore o uguale , è semplice come cambiare l'operatore di confronto della valutazione aritmetica (cioè (( ${version_1%%.*} >= "${version_2%%.*}" )) ).

    
risposta data 22.03.2013 - 00:35
fonte
0

Posso darti un lungo esempio di "se la versione controllata è tra min e max" e puoi ottimizzarlo per le tue esigenze cambiando la testa -1 / tail -1 e tagliando 1 variabile:

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
    
risposta data 06.03.2014 - 21:08
fonte
0

Ecco un'altra soluzione che:

  • non esegue alcun comando esterno oltre a tr
  • non ha restrizioni sul numero di parti nella stringa di versione
  • può confrontare le stringhe di versione con un numero diverso di parti

Si noti che è il codice Bash che usa le variabili dell'array.

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 funzione restituisce:

  • 0 se le versioni sono uguali (btw: 1.2 == 1.2.0)
  • 1 se la prima versione è più grande / più recente
  • 2 se la seconda versione è più grande / più recente

Tuttavia # 1 - richiede una funzione aggiuntiva (ma la funzione min è abbastanza utilizzabile comunque):

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

Tuttavia # 2 - non può confrontare le stringhe di versione con parti alfanumeriche (anche se in realtà non sarebbe difficile da aggiungere).

    
risposta data 21.11.2016 - 19:34
fonte
0

Puoi utilizzare la versione della CLI per verificare i vincoli della versione

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

Esempio di script Bash:

#!/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
    
risposta data 25.02.2018 - 15:13
fonte

Leggi altre domande sui tag