Existe-t-il un moyen de comparer de telles chaînes sur bash, par exemple: 2.4.5
et 2.8
et 2.4.5.1
?
linux
bash
versioning
exabiche
la source
la source
bc
. Ce n'est pas du texte, pas des chiffres.2.1 < 2.10
échouerait de cette façon.Réponses:
Voici une version pure de Bash qui ne nécessite aucun utilitaire externe:
Exécutez les tests:
la source
Please don't use it for software or documentation, since it is incompatible with the GNU GPL
: / mais +1 pour un excellent codeSi vous avez coreutils-7 (dans Ubuntu Karmic mais pas Jaunty), votre
sort
commande devrait avoir une-V
option (tri de version) que vous pouvez utiliser pour faire la comparaison:la source
brew install coreutils
. Ensuite, ce qui précède devrait simplement être modifié pour utiliser gsort.sort
n'a pas d'-V
option.printf
au lieu deecho -e
.sort
aussi-C
ou--check=silent
, donc vous pouvez écrireverlte() { printf '%s\n%s' "$1" "$2" | sort -C -V }
; et vérifier moins strict que ce qui est plus simplement faitverlt() { ! verlte "$2" "$1" }
.Il n'y a probablement pas de moyen universellement correct d'y parvenir. Si vous essayez de comparer les versions du système de paquets Debian, essayez
dpkg --compare-versions <first> <relation> <second>.
la source
dpkg --compare-versions "1.0" "lt" "1.2"
signifie 1,0 de moins que 1,2. Le résultat de la comparaison$?
est0
si vrai, vous pouvez donc l'utiliser directement après l'if
instruction.Le tri GNU a une option pour cela:
donne:
la source
echo -e "2.4.10\n2.4.9" | sort -n -t.
sort
n'a pas d'-V
option.printf '%s\n' "2.4.5" "2.8" "2.4.5.1" | sort -V
.coreutils 7+
.Eh bien, si vous connaissez le nombre de champs, vous pouvez utiliser -kn, n et obtenir une solution super simple
la source
-t
option n'accepte que les onglets à un seul caractère ... sinon,2.4-r9
cela fonctionnerait aussi. Quelle honte: /-g
à-n
. Une raison pourquoi pas pour cet exemple? Sur une note latérale ... pour effectuer une comparaison de type "supérieur à", vous pouvez vérifier si le tri souhaité est le même que le tri réel ... par exempledesired="1.9\n1.11"; actual="$(echo -e $desired |sort -t '.' -k 1,1 -k 2,2 -g)";
, puis vérifierif [ "$desired" = "$actual" ]
.Ceci concerne au plus 4 champs de la version.
la source
printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4)
head -n
travailler, je devais changer pourtr '.' '\n'
tr
Sortie de tuyau à traverssed 's/\(^\| \)0\([0-9][0-9]*\)/\1\2/g'
laquelle s'occupera de cela (plutôt maladroitement)Utilisé comme tel:
(à partir de https://apple.stackexchange.com/a/123408/11374 )
la source
Vous pouvez fractionner
.
et comparer récursivement comme indiqué dans l'algorithme suivant, tiré d' ici . Il renvoie 10 si les versions sont identiques, 11 si la version 1 est supérieure à la version 2 et 9 sinon.La source
la source
s'il s'agit juste de savoir si une version est inférieure à une autre, je suis venu vérifier si
sort --version-sort
l'ordre de mes chaînes de version change:la source
J'ai implémenté une fonction qui renvoie les mêmes résultats que Dennis Williamson mais utilise moins de lignes. Il effectue un contrôle de cohérence au départ, ce qui fait
1..0
échouer ses tests (ce qui, je dirais, devrait être le cas), mais tous ses autres tests réussissent avec ce code:la source
Voici une simple fonction Bash qui n'utilise aucune commande externe. Cela fonctionne pour les chaînes de version contenant jusqu'à trois parties numériques - moins de 3 convient également. Il peut facilement être prolongé pour plus. Il met en œuvre
=
,<
,<=
,>
,>=
et les!=
conditions.Voici le test:
Un sous-ensemble de la sortie de test:
la source
V
- solution pure bash, aucun utilitaire externe requis.=
==
!=
<
<=
>
et>=
(lexicographique).1.5a < 1.5b
1.6 > 1.5b
if V 1.5 '<' 1.6; then ...
.<>
<>
Code expliqué
Ligne 1 : définir les variables locales:
a
,op
,b
-, "3.6"> "3.5a" opérandes de comparaison et l' opérateur, par exemple.al
,bl
- queues de lettres dea
etb
, initialisées à l'élément de queue, c'est-à-dire "6" et "5a".Lignes 2, 3 : Découpez à gauche les chiffres des éléments de fin de sorte que seules les lettres soient laissées, le cas échéant, c'est-à-dire "" et "a".
Ligne 4 : Coupez les lettres à droite de
a
etb
pour ne laisser que la séquence d'éléments numériques en tant que variables localesai
etbi
, c'est-à-dire "3,6" et "3,5". Exemple notable: "4.01-RC2"> "4.01-RC1" donne ai = "4.01" al = "- RC2" et bi = "4.01" bl = "- RC1".Ligne 6 : Définissez les variables locales:
ap
,bp
- zéro rembourrage à droite pourai
etbi
. Commencez par ne conserver que les points inter-éléments, dont le nombre est égal au nombre d'éléments dea
etb
respectivement.Ligne 7 : puis ajoutez "0" après chaque point pour créer des masques de remplissage.
Ligne 9 : Variables locales:
w
- largeur de l'articlefmt
- chaîne de format printf, à calculerx
- temporaireIFS=.
bash divise les valeurs des variables en «.».Ligne 10 : Calculez
w
, la largeur maximale de l'élément, qui sera utilisée pour aligner les éléments pour la comparaison lexicographique. Dans notre exemple w = 2.Ligne 11 : Créez le format d'alignement printf en remplaçant chaque caractère de
$a.$b
par%${w}s
, c'est-à-dire que "3.6"> "3.5a" donne "% 2s% 2s% 2s% 2s".Ligne 12 : "printf -v a" définit la valeur de la variable
a
. Ceci est équivalent àa=sprintf(...)
dans de nombreux langages de programmation. Notez qu'ici, par effet de IFS =. les arguments pourprintf
diviser en éléments individuels.Les premiers
printf
éléments dea
sont remplis à gauche avec des espaces tandisbp
qu'un nombre suffisant d'éléments "0" sont ajoutés pour garantir que la chaîne résultantea
peut être comparée de manière significative à un format similaireb
.Notez que nous ajoutons
bp
- pasap
àai
causeap
etbp
peut avoir différentes longueurs, donc cela se traduit para
etb
ayant des longueurs égales.Avec le second,
printf
nous ajoutons la partie lettreal
àa
avec suffisamment de remplissage pour permettre une comparaison significative.a
Est maintenant prêt pour la comparaison avecb
.Ligne 13 : identique à la ligne 12 mais pour
b
.Ligne 15 : Scinder les cas de comparaison entre les cas non intégrés (
<=
et>=
opérateurs ) et intégrés.Ligne 16 : Si l'opérateur de comparaison est
<=
alors tester poura<b or a=b
- respectivement>=
a<b or a=b
Ligne 17 : test des opérateurs de comparaison intégrés.
<>
la source
J'utilise Linux embarqué (Yocto) avec BusyBox. BusyBox
sort
n'a pas d'-V
option (mais BusyBoxexpr match
peut faire des expressions régulières). J'avais donc besoin d'une comparaison de version Bash qui fonctionnait avec cette contrainte.J'ai fait ce qui suit (similaire à la réponse de Dennis Williamson ) pour comparer en utilisant un type d'algorithme de "tri naturel". Il divise la chaîne en parties numériques et en parties non numériques; il compare numériquement les parties numériques (donc
10
est supérieur à9
) et compare les parties non numériques comme une simple comparaison ASCII.Il peut comparer des numéros de version plus compliqués tels que
1.2-r3
contre1.2-r4
1.2rc3
contre1.2r4
Notez qu'il ne renvoie pas le même résultat pour certains des cas de coin dans la réponse de Dennis Williamson . En particulier:
Mais ce sont des cas de coin, et je pense que les résultats sont encore raisonnables.
la source
la source
--check=silent
, sans avoir besoin detest
, comme ceci:if printf '%s\n%s' 4.2.0 "$OVFTOOL_VERSION" | sort --version-sort -C
C'est aussi une
pure bash
solution, car printf est un bash intégré.la source
Pour l'ancienne version / busybox
sort
. La forme simple fournit un résultat approximatif et fonctionne souvent.C'est escpecial utile sur la version qui contient des symboles alpha comme
la source
Que dis-tu de ça? Semble fonctionner?
la source
Voici une autre solution pure bash sans aucun appel externe:
Et il existe une solution encore plus simple, si vous êtes sûr que les versions en question ne contiennent pas de zéros non significatifs après le premier point:
Cela fonctionnera pour quelque chose comme 1.2.3 vs 1.3.1 vs 0.9.7, mais ne fonctionnera pas avec 1.2.3 vs 1.2.3.0 ou 1.01.1 vs 1.1.1
la source
4.4.4 > 44.3
Voici un raffinement de la première réponse (celle de Dennis) qui est plus concise et utilise un schéma de valeur de retour différent pour faciliter l'implémentation de <= et> = avec une seule comparaison. Il compare également tout ce qui suit le premier caractère pas dans [0-9.] Lexicographiquement, donc 1.0rc1 <1.0rc2.
la source
J'ai implémenté une autre fonction de comparateur. Celui-ci avait deux exigences spécifiques: (i) je ne voulais pas que la fonction échoue en utilisant
return 1
mais à laecho
place; (ii) comme nous récupérons les versions d'un référentiel git, la version "1.0" devrait être plus grande que "1.0.2", ce qui signifie que "1.0" provient du tronc.N'hésitez pas à commenter et suggérer des améliorations.
la source
Vous pouvez utiliser la version CLI pour vérifier les contraintes de la version
Exemple de script Bash:
la source
Je suis tombé sur et j'ai résolu ce problème, pour ajouter une réponse supplémentaire (et plus courte et plus simple) ...
Première note, la comparaison de shell étendue a échoué comme vous le savez peut-être déjà ...
En utilisant le tri -t '.'- g (ou sort -V comme mentionné par kanaka) pour commander les versions et une simple comparaison de chaînes de caractères bash, j'ai trouvé une solution. Le fichier d'entrée contient des versions dans les colonnes 3 et 4 que je souhaite comparer. Cela parcourt la liste en identifiant une correspondance ou si l'une est supérieure à l'autre. J'espère que cela peut encore aider tous ceux qui cherchent à le faire en utilisant bash aussi simple que possible.
Merci au blog de Barry pour l'idée de tri ... ref: http://bkhome.org/blog/?viewDetailed=02199
la source
C'est assez simple et petit.
la source
echo -ne "$1\n$2"
parprintf '%s\n ' "$1" "$2"
. Il est également préférable d'utiliser à la$()
place des backtics.Grâce à la solution de Dennis, nous pouvons l'étendre pour autoriser les opérateurs de comparaison '>', '<', '=', '==', '<=' et '> ='.
Nous pouvons ensuite utiliser des opérateurs de comparaison dans les expressions telles que:
et testez uniquement le vrai / faux du résultat, comme:
la source
Voici une autre version pure bash, plutôt plus petite que la réponse acceptée. Il vérifie uniquement si une version est inférieure ou égale à une "version minimale", et il vérifie les séquences alphanumériques lexicographiquement, ce qui donne souvent un résultat erroné ("snapshot" n'est pas postérieur à "release", pour donner un exemple courant) . Cela fonctionnera bien pour majeur / mineur.
la source
Une autre approche (version modifiée de @joynes) qui compare les versions pointées posées dans la question
(ie "1.2", "2.3.4", "1.0", "1.10.1", etc.).
Le nombre maximum de postes doit être connu à l'avance. L'approche attend au maximum 3 positions de version.
exemple d'utilisation:
renvoie: 1 puisque 1.10.1 est plus grand que 1.7
renvoie: 0 car 1.10.1 est inférieur à 1.11
la source
Voici une solution pure Bash qui prend en charge les révisions (par exemple '1.0-r1'), basée sur la réponse publiée par Dennis Williamson . Il peut facilement être modifié pour prendre en charge des éléments tels que «-RC1» ou extraire la version d'une chaîne plus complexe en modifiant l'expression régulière.
Pour plus de détails concernant l'implémentation, reportez-vous aux commentaires dans le code et / ou activez le code de débogage inclus:
la source
Wow ... c'est bien en bas de la liste d'une vieille question, mais je pense que c'est une réponse assez élégante. Commencez par convertir chaque version séparée par des points dans son propre tableau, en utilisant l'expansion des paramètres du shell (voir Expansion des paramètres du shell ).
Désormais, les deux tableaux ont le numéro de version sous forme de chaîne numérique par ordre de priorité. Beaucoup de solutions ci-dessus vous amènent à partir de là, mais tout dérive de l'observation que la chaîne de version est juste un entier avec une base arbitraire. Nous pouvons tester la recherche du premier chiffre différent (comme strcmp le fait pour les caractères d'une chaîne).
Cela fait écho à un nombre négatif si la première version est inférieure à la seconde, un zéro si elles sont égales et un nombre positif si la première version est supérieure. Quelques sorties:
Cas dégénérés comme ".2" ou "3.0". ne fonctionne pas (résultats non définis), et si des caractères non numériques sont présents à côté du '.' il pourrait échouer (pas testé) mais sera certainement indéfini. Cela doit donc être associé à une fonction de désinfection ou à une vérification appropriée du formatage valide. De plus, je suis sûr qu'avec quelques ajustements, cela pourrait être rendu plus robuste sans trop de bagages supplémentaires.
la source
Le crédit revient à @Shellman
la source