Vergleichen Sie mehrstellige Versionsnummern in Bash

4

Beim Versuch, ein Skript zu schreiben, das nach der Version der Anwendung sucht, wird der Wert zurückgegeben. Mein Problem ist, dass der Wert drei bis vier Einsätze lang ist (Beispiel 4.3.2).

Ich habe nach einer Weile gesucht und kann keine Syntax finden, die es Ihnen erlaubt, ein! = Oder -ge für alle Nummern zu verwenden, die höher sind als eine Zahl mit Punkten. Ich frage mich nur, ob jemand einen besseren Weg hat, oder ich werde einfach für jede Version weitere hinzufügen.

Was ich möchte

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

Wie steht es jetzt geschrieben?

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
balooga1
quelle
Die Lösung, mit der Matteo verbunden ist, scheint viel komplizierter als nötig zu sein, es sei denn, ich verstehe etwas. Ich habe unten eine kürzere Lösung veröffentlicht.
TJ Luoma
BTW mdls -raw -name kMDItemVersion /Applications/iMovie.app gibt Ihnen nur die Versionsnummer ohne das überflüssige Zeug.
TJ Luoma

Antworten:

1

Ich glaube, ich habe das etwas angepasst http://bashscripts.org/forum/viewtopic.php?f=16&t=1248 . Ich mag es, weil es ziemlich kompakt und lesbar ist.

Dies ist optional, aber wünschenswert IMO:

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

Hier ist das Fleisch:

Ich benutze immer $1 für "die lokal installierte Version" und $2 für "die Version, mit der ich vergleiche", also wenn mir das so bleibt $? = 1 Ich muss aktualisieren, ansonsten bin ich auf dem neuesten Stand (oder sogar voraus):

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

Wenn Sie sich nur darum gekümmert hätten, ob $1 war auf dem neuesten Stand (dh gleich oder größer als $2 ) Sie könnten es noch einfacher machen:

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

Nachfolgender Code wird nur ausgeführt, wenn eine neuere Version verfügbar ist. Andernfalls wird das Skript an diesem Punkt sauber beendet.

p .: Ich mache das in / bin / zsh nicht / bin / bash aber nicht denken In diesem Fall macht es einen Unterschied.

TJ Luoma
quelle
0

Tatsächlich ist der Vergleich von Versionsnummern ziemlich einfach (zumindest solange sie streng numerisch sind), da sie hierarchisch von links nach rechts strukturiert sind. Ein sequenzieller Vergleich in derselben Reihenfolge führt zu einem eindeutigen Ergebnis.

Folgende bash Funktion gibt 0 (wahr) zurück, wenn zwei Versionsnummern vorhanden sind nicht gleich , 1 (false), wenn dies der Fall ist, solange die Variablen vorhanden sind $version_1 und $version_2 beide enthalten nur eine beliebige Anzahl von Zifferngruppen, die durch Punkte getrennt sind:

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
}

Implementierung anderer Vergleiche, wie größer oder gleich , ist so einfach wie das Ändern des Vergleichsoperators der arithmetischen Bewertung (d. h. (( ${version_1%%.*} >= "${version_2%%.*}" )) ).

kopischke
quelle
0

Ich kann Ihnen ein langes Beispiel geben "wenn die geprüfte Version zwischen min und max liegt" und Sie können sie für Ihre Bedürfnisse optimieren, indem Sie den Kopf -1 / Schwanz -1 ändern und 1 Variable schneiden:

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
Svetozar Urumov
quelle
0

Hier ist eine andere Lösung, die:

  • führt keinen externen Befehl außer. aus tr
  • hat keine Einschränkung für die Anzahl der Teile in der Versionszeichenfolge
  • kann Versionsstrings mit unterschiedlicher Anzahl von Teilen vergleichen

Beachten Sie, dass es sich um Bash-Code handelt, der Array-Variablen verwendet.

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
}

Die Funktion gibt zurück:

  • 0 wenn Versionen gleich sind (btw: 1.2 == 1.2.0)
  • 1, wenn die 1. Version größer / neuer ist
  • 2 wenn die 2. Version größer / neuer ist

Jedoch # 1 erfordert eine zusätzliche Funktion (aber Funktion min ist durchaus brauchbar zu haben):

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

Allerdings # 2 - Versionszeichenfolgen können nicht mit alphanumerischen Teilen verglichen werden (obwohl dies eigentlich nicht schwierig ist, hinzugefügt zu werden).

mato
quelle
0

Sie können verwenden Ausführung CLI, um die Einschränkungen der Version zu überprüfen

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

Beispiel für ein Bash-Skript:

#!/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
Ivan Dyachenko
quelle