Gibt es eine Möglichkeit, solche Zeichenfolgen mit Bash zu vergleichen, z. B.: 2.4.5
Und 2.8
und 2.4.5.1
?
linux
bash
versioning
exabiche
quelle
quelle
bc
. Es ist Text, keine Zahlen.2.1 < 2.10
würde auf diese Weise scheitern.Antworten:
Hier ist eine reine Bash-Version, für die keine externen Dienstprogramme erforderlich sind:
Führen Sie die Tests aus:
quelle
Please don't use it for software or documentation, since it is incompatible with the GNU GPL
: / aber +1 für großartigen CodeWenn Sie coreutils-7 haben (in Ubuntu Karmic, aber nicht Jaunty), sollte Ihr
sort
Befehl eine-V
Option (Versionssortierung) haben, mit der Sie den Vergleich durchführen können:quelle
brew install coreutils
. Dann sollte das Obige nur geändert werden, um gsort zu verwenden.sort
keine-V
Option hat.printf
alsecho -e
.sort
hat auch-C
oder--check=silent
, damit Sie schreiben könnenverlte() { printf '%s\n%s' "$1" "$2" | sort -C -V }
; und streng weniger prüfen, als einfacher gemacht wird alsverlt() { ! verlte "$2" "$1" }
.Es gibt wahrscheinlich keinen allgemein korrekten Weg, um dies zu erreichen. Wenn Sie versuchen, Versionen im Debian-Paketsystem zu vergleichen, versuchen Sie es
dpkg --compare-versions <first> <relation> <second>.
quelle
dpkg --compare-versions "1.0" "lt" "1.2"
bedeutet 1,0 weniger als 1,2. Das Vergleichsergebnis$?
ist0
if true, sodass Sie es direkt nach derif
Anweisung verwenden können.Die GNU-Sortierung hat eine Option:
gibt:
quelle
echo -e "2.4.10\n2.4.9" | sort -n -t.
sort
keine-V
Option hat.printf '%s\n' "2.4.5" "2.8" "2.4.5.1" | sort -V
.coreutils 7+
.Wenn Sie die Anzahl der Felder kennen, können Sie -kn, n verwenden und eine supereinfache Lösung erhalten
quelle
-t
Option akzeptiert nur Registerkarten mit nur einem Zeichen. Andernfalls2.4-r9
würde dies auch funktionieren. Was für eine Schande: /-g
zu-n
. Gibt es einen Grund, warum nicht für dieses Beispiel? Nebenbei bemerkt ... um einen Typvergleich "größer als" durchzuführen, können Sie überprüfen, ob die gewünschte Sortierung mit der tatsächlichen Sortierung übereinstimmt ... z . B.desired="1.9\n1.11"; actual="$(echo -e $desired |sort -t '.' -k 1,1 -k 2,2 -g)";
und dann überprüfenif [ "$desired" = "$actual" ]
.Dies gilt für höchstens 4 Felder in der Version.
quelle
printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4)
head -n
zu arbeiten, musste ich zutr '.' '\n'
tr
durchsed 's/\(^\| \)0\([0-9][0-9]*\)/\1\2/g'
die das erledigt wird (Als solches verwendet:
(von https://apple.stackexchange.com/a/123408/11374 )
quelle
Sie können aufgeteilt auf rekursiv
.
und vergleichen , wie in den folgenden Algorithmus, aus genommen ist hier . Es gibt 10 zurück, wenn die Versionen identisch sind, 11, wenn Version 1 größer als Version 2 ist, und 9, wenn dies nicht der Fall ist.Quelle
quelle
Wenn es nur darum geht zu wissen, ob eine Version niedriger als eine andere ist, habe ich geprüft, ob
sort --version-sort
sich die Reihenfolge meiner Versionszeichenfolgen ändert:quelle
Ich habe eine Funktion implementiert, die dieselben Ergebnisse wie Dennis Williamsons zurückgibt, jedoch weniger Zeilen verwendet. Zunächst wird eine Überprüfung der geistigen Gesundheit durchgeführt, die dazu führt
1..0
, dass seine Tests fehlschlagen (was ich argumentieren würde) , soll der Fall sein) , aber alle seine anderen Tests bestehen , mit diesem Code:quelle
Hier ist eine einfache Bash-Funktion, die keine externen Befehle verwendet. Es funktioniert für Versionszeichenfolgen mit bis zu drei numerischen Teilen - weniger als 3 sind ebenfalls in Ordnung. Es kann leicht für mehr erweitert werden. Es implementiert
=
,<
,<=
,>
,>=
, und!=
Bedingungen.Hier ist der Test:
Eine Teilmenge der Testausgabe:
quelle
V
- reine Bash-Lösung, keine externen Dienstprogramme erforderlich.=
==
!=
<
<=
>
und>=
(lexikografisch).1.5a < 1.5b
1.6 > 1.5b
if V 1.5 '<' 1.6; then ...
.<>
<>
Code erklärt
Zeile 1 : Lokale Variablen definieren:
a
,op
,b
- Vergleichsoperanden und Operator, das heißt, "3.6"> "3.5a".al
,bl
- Buchstabenschwänze vona
undb
, initialisiert auf das Endstück, dh "6" und "5a".Zeilen 2, 3 : Ziffern links von den Endelementen, sodass nur noch Buchstaben übrig sind, z. B. "" und "a".
Zeile 4 : Rechte Trimmbuchstaben von
a
undb
, um nur die Folge numerischer Elemente als lokale Variablen zu belassenai
und zubi
dh "3.6" und "3.5" zu belassen. Bemerkenswertes Beispiel: "4.01-RC2"> "4.01-RC1" ergibt ai = "4.01" al = "- RC2" und bi = "4.01" bl = "- RC1".Zeile 6 : Lokale Variablen definieren:
ap
,bp
- Null Rechtspolster fürai
undbi
. Starten Sie durch die Zwischenelement - Punkte nur zu halten, von welcher Nummer die Anzahl der Elemente gleicha
undb
jeweils.Zeile 7 : Fügen Sie dann nach jedem Punkt "0" hinzu, um Füllmasken zu erstellen.
Zeile 9 : Lokale Variablen:
w
- Artikelbreitefmt
- zu berechnende printf-Formatzeichenfolgex
- vorübergehendIFS=.
Bash werden variable Werte bei '.' Aufgeteilt.Zeile 10 : Berechnen Sie
w
die maximale Elementbreite, die zum Ausrichten von Elementen für den lexikografischen Vergleich verwendet wird. In unserem Beispiel ist w = 2.Zeile 11 : Erstellen der printf Ausrichtungsformat , das von einzelnen Zeichen zu ersetzen ,
$a.$b
mit%${w}s
, das heißt, "3.6"> "3.5a" Ausbeute "% 2s% 2s% 2s% 2s".Zeile 12 : "printf -v a" legt den Wert der Variablen fest
a
. Dies entsprichta=sprintf(...)
in vielen Programmiersprachen. Beachten Sie, dass hier durch Wirkung von IFS =. die Argumente,printf
die in einzelne Elemente aufgeteilt werden sollen.Bei den ersten
printf
Elementena
werden links Leerzeichen aufgefüllt, während genügend "0" -Elemente angehängt werden,bp
um sicherzustellen, dass die resultierende Zeichenfolgea
sinnvoll mit einer ähnlich formatierten verglichen werden kannb
.Beachten Sie, dass wir anhängen
bp
- nichtap
an,ai
weilap
undbp
möglicherweise unterschiedliche Längen haben, so dass dies zua
undb
mit gleichen Längen führt.Mit dem zweiten
printf
fügen wir den Brief Teilal
ana
mit genügend Polsterung zu aussagekräftigen Vergleich zu ermöglichen. Jetzta
ist zum Vergleich bereit mitb
.Zeile 13 : Wie Zeile 12, jedoch für
b
.Zeile 15 : Aufteilen von Vergleichsfällen zwischen nicht integrierten (
<=
und>=
) und integrierten Operatoren.Zeile 16 : Wenn der Vergleichsoperator ist,
<=
testen Sie aufa<b or a=b
- jeweils>=
a<b or a=b
Zeile 17 : Test für eingebaute Vergleichsoperatoren.
<>
quelle
Ich verwende Embedded Linux (Yocto) mit BusyBox. BusyBox
sort
hat keine-V
Option (aber BusyBoxexpr match
kann reguläre Ausdrücke ausführen ). Also brauchte ich einen Bash-Versionsvergleich, der mit dieser Einschränkung funktionierte.Ich habe Folgendes gemacht (ähnlich wie Dennis Williamsons Antwort ), um es mit einem Algorithmus vom Typ "natürliche Art" zu vergleichen. Es teilt die Zeichenfolge in numerische Teile und nicht numerische Teile auf. Es vergleicht die numerischen Teile numerisch (
10
ist also größer als9
) und vergleicht die nicht numerischen Teile als einfachen ASCII-Vergleich.Es kann kompliziertere Versionsnummern wie z
1.2-r3
gegen1.2-r4
1.2rc3
gegen1.2r4
Beachten Sie, dass für einige der Eckfälle in Dennis Williamsons Antwort nicht das gleiche Ergebnis zurückgegeben wird . Bestimmtes:
Aber das sind Eckfälle, und ich denke, die Ergebnisse sind immer noch vernünftig.
quelle
quelle
--check=silent
, ohne dasstest
dies erforderlich ist:if printf '%s\n%s' 4.2.0 "$OVFTOOL_VERSION" | sort --version-sort -C
Dies ist auch eine
pure bash
Lösung, da printf eine eingebaute Bash ist.quelle
Für alte Version / Busybox
sort
. Einfache Form liefern ungefähr Ergebnisse und funktionieren oft.Dies ist besonders nützlich bei Versionen, die Alpha-Symbole wie enthalten
quelle
Wie wäre es damit? Scheint zu funktionieren?
quelle
Hier ist eine weitere reine Bash-Lösung ohne externe Anrufe:
Und es gibt eine noch einfachere Lösung, wenn Sie sicher sind, dass die fraglichen Versionen keine führenden Nullen nach dem ersten Punkt enthalten:
Dies funktioniert für etwas wie 1.2.3 gegen 1.3.1 gegen 0.9.7, aber nicht für 1.2.3 gegen 1.2.3.0 oder 1.01.1 gegen 1.1.1
quelle
4.4.4 > 44.3
Hier ist eine Verfeinerung der Top-Antwort (Dennis's), die präziser ist und ein anderes Rückgabewertschema verwendet, um die Implementierung von <= und> = mit einem einzigen Vergleich zu vereinfachen. Es vergleicht auch alles nach dem ersten Zeichen nicht in [0-9.] Lexikographisch, also 1.0rc1 <1.0rc2.
quelle
Ich habe noch eine weitere Komparatorfunktion implementiert. Dieser hatte zwei spezifische Anforderungen: (i) Ich wollte nicht, dass die Funktion durch Verwendung von
return 1
sondern fehlschlägtecho
; (ii) Da wir Versionen aus einem Git-Repository abrufen, sollte "1.0" größer als "1.0.2" sein, was bedeutet, dass "1.0" aus dem Trunk stammt.Fühlen Sie sich frei zu kommentieren und Verbesserungen vorzuschlagen.
quelle
Sie können die Versions- CLI verwenden, um die Einschränkungen der Version zu überprüfen
Beispiel für ein Bash-Skript:
quelle
Ich bin auf dieses Problem gestoßen und habe es gelöst, um eine zusätzliche (und kürzere und einfachere) Antwort hinzuzufügen ...
Erster Hinweis: Der erweiterte Shell-Vergleich ist fehlgeschlagen, wie Sie vielleicht bereits wissen ...
Mit der Sortierung -t '.'- g (oder der Sortierung -V, wie von Kanaka erwähnt) zum Bestellen von Versionen und zum einfachen Vergleich von Bash-Strings habe ich eine Lösung gefunden. Die Eingabedatei enthält Versionen in den Spalten 3 und 4, die ich vergleichen möchte. Dies durchläuft die Liste und identifiziert eine Übereinstimmung oder wenn eine größer als die andere ist. Ich hoffe, dies kann immer noch jedem helfen, der dies mit Bash so einfach wie möglich machen möchte.
Vielen Dank an Barrys Blog für die Sortieridee ... ref: http://bkhome.org/blog/?viewDetailed=02199
quelle
Es ist ziemlich einfach und klein.
quelle
echo -ne "$1\n$2"
mitprintf '%s\n ' "$1" "$2"
. Es ist auch besser,$()
anstelle der Backtics zu verwenden.Dank Dennis 'Lösung können wir sie erweitern, um Vergleichsoperatoren'> ',' <',' = ',' == ',' <= 'und'> = 'zu ermöglichen.
Wir können dann Vergleichsoperatoren in folgenden Ausdrücken verwenden:
und testen Sie nur das Richtig / Falsch des Ergebnisses, wie:
quelle
Hier ist eine weitere reine Bash-Version, die eher kleiner als die akzeptierte Antwort ist. Es wird nur geprüft, ob eine Version kleiner oder gleich einer "Mindestversion" ist, und es werden alphanumerische Sequenzen lexikografisch überprüft, was häufig zu einem falschen Ergebnis führt ("Schnappschuss" ist nicht später als "Veröffentlichung", um ein allgemeines Beispiel zu nennen). . Es wird gut für Dur / Moll funktionieren.
quelle
Ein anderer Ansatz (modifizierte Version von @joynes), der gepunktete Versionen vergleicht, wie in der Frage gestellt
(dh "1.2", "2.3.4", "1.0", "1.10.1" usw.).
Die maximale Anzahl von Positionen muss im Voraus bekannt sein. Der Ansatz erwartet maximal 3 Versionspositionen.
Anwendungsbeispiel:
Rückgabe: 1, da 1.10.1 größer als 1.7 ist
Rückgabe: 0, da 1.10.1 niedriger als 1.11 ist
quelle
Hier ist eine reine Bash-Lösung, die Revisionen unterstützt (z. B. '1.0-r1'), basierend auf der Antwort von Dennis Williamson . Es kann leicht geändert werden, um Dinge wie '-RC1' zu unterstützen oder die Version aus einer komplexeren Zeichenfolge zu extrahieren, indem der reguläre Ausdruck geändert wird.
Einzelheiten zur Implementierung finden Sie in den In-Code-Kommentaren und / oder aktivieren Sie den enthaltenen Debug-Code:
quelle
Wow ... das ist ganz unten auf der Liste einer alten Frage, aber ich denke, das ist eine ziemlich elegante Antwort. Konvertieren Sie zuerst jede durch Punkte getrennte Version mithilfe der Shell-Parametererweiterung in ein eigenes Array (siehe Shell-Parametererweiterung ).
Jetzt haben die beiden Arrays die Versionsnummer als numerische Zeichenfolge in Prioritätsreihenfolge. Viele der oben genannten Lösungen führen Sie von dort aus, aber alles ergibt sich aus der Beobachtung, dass die Versionszeichenfolge nur eine Ganzzahl mit einer beliebigen Basis ist. Wir können testen, ob die erste ungleiche Ziffer gefunden wurde (wie es strcmp für Zeichen in einer Zeichenfolge tut).
Dies gibt eine negative Zahl wieder, wenn die erste Version kleiner als die zweite ist, eine Null, wenn sie gleich sind, und eine positive Zahl, wenn die erste Version größer ist. Einige Ausgaben:
Entartete Fälle wie ".2" oder "3.0". funktioniert nicht (undefinierte Ergebnisse) und wenn nicht numerische Zeichen neben dem '.' vorhanden sind. es könnte fehlschlagen (nicht getestet), wird aber sicherlich undefiniert sein. Dies sollte daher mit einer Desinfektionsfunktion oder einer entsprechenden Überprüfung auf gültige Formatierung kombiniert werden. Ich bin mir auch sicher, dass dies mit einigen Optimierungen ohne zu viel zusätzliches Gepäck robuster gemacht werden könnte.
quelle
Das Guthaben geht an @Shellman
quelle