Frage

Ich habe eine Versionsnummer der folgenden Form:

version.release.modification

Dabei steht Version, Release und Modifikation sind entweder ein Satz von Ziffern oder ‚*‘ Wildcard-Zeichen. Zusätzlich kann jede dieser Zahlen (und einer der vorhergehende.) Fehlen.

So ist die folgende gültig und parsen, wie:

1.23.456 = version 1, release 23, modification 456
1.23     = version 1, release 23, any modification
1.23.*   = version 1, release 23, any modification
1.*      = version 1, any release, any modification
1        = version 1, any release, any modification
*        = any version, any release, any modification

Aber diese sind nicht gültig:

*.12
*123.1
12*
12.*.34

Kann jemand geben Sie mir eine nicht allzu komplexe Regex zu validieren und Abrufen der Release-Version und Änderungsnummern?

War es hilfreich?

Lösung

Ich würde ausdrücken das Format wie:

  

„1-3 Punkte getrennte Komponenten, wobei jede numerische Ausnahme, dass das letzte * sein kann“

Als regexp, das ist:

^(\d+\.)?(\d+\.)?(\*|\d+)$

[Bearbeiten hinzuzufügen: diese Lösung ein kurzer Weg ist, zu bestätigen, aber es wurde darauf hingewiesen, dass die Werte Extra erfordert Arbeit zu extrahieren. Es ist eine Frage des Geschmacks, ob damit umgehen, indem die regexp verkomplizieren oder durch die angepassten Gruppen zu verarbeiten.

In meiner Lösung, erfassen die Gruppen die "." Zeichen. Dies kann bei der Verwendung von nicht-einfangenden Gruppen wie in ajborley Antwort behandelt werden.

Außerdem wird die rechte Gruppe die letzte Komponente erfassen, auch wenn es weniger als drei Komponenten, und so beispielsweise ein Zwei-Komponenten-Eingang Ergebnisse in den ersten und letzten Gruppen zu erfassen und die mittleren undefiniert. Ich denke, das durch nicht-gierige Gruppen behandelt werden kann, wo unterstützt.

Perl-Code mit beiden Fragen zu beschäftigen, nachdem die regexp so etwas wie dies sein könnte:

@version = ();
@groups = ($1, $2, $3);
foreach (@groups) {
    next if !defined;
    s/\.//;
    push @version, $_;
}
($major, $minor, $mod) = (@version, "*", "*");

Was nicht wirklich kürzer als Splitting auf "." ist ]

Andere Tipps

Verwenden regex und jetzt haben Sie zwei Probleme. Ich würde die Sache auf Punkte geteilt ( „“), dann stellen Sie sicher, dass jeder Teil entweder ein Platzhalter oder eine Reihe von Ziffern (regex ist perfekt jetzt). Wenn das Ding gültig ist, müssen Sie nur richtige Brocken des geteilten zurück.

Dies könnte funktionieren:

^(\*|\d+(\.\d+){0,2}(\.\*)?)$

Auf der obersten Ebene, „*“ ist ein Sonderfall eines gültigen Versionsnummer. Andernfalls beginnt es mit einer Nummer. Dann gibt es keinen, einen oder zwei „.nn“ Sequenzen, gefolgt von einer optionalen „*“. Diese Regex würde 1.2.3 akzeptieren. *, Die möglicherweise nicht in Ihrer Anwendung erlaubt sein.

Der Code die passenden Sequenzen für das Abrufen, vor allem des (\.\d+){0,2} Teil wird auf Ihrer spezielle regex Bibliothek ab.

Danke für alle Antworten! Dies ist ace:)

Basierend auf OneByOne Antwort (die die einfachste mir sah), habe ich ein paar nicht-einfangenden Gruppen (das ‚(:‘! Teile - dank VonC für mich zu nicht-einfangenden Gruppen einzuführen), so die Gruppen, die Sie erfassen nur die Ziffern enthalten oder Zeichen *.

^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$

Vielen Dank alle!

Sie wissen nicht, welche Plattform sind Sie auf, aber in .NET gibt die System.Version Klasse ist die „n.n.n.n“ Versionsnummern für Sie analysieren.

Meine 2 Cent: Ich habe dieses Szenario hatte: Ich Versionsnummern aus einem String-Literal zu analysieren hatte. (Ich weiß, das von der ursprünglichen Frage sehr unterschiedlich, aber googel einen regulären Ausdruck zu finden für das Parsen von Versionsnummer zeigte dieses Thema an der Spitze, so das Hinzufügen dieser Antwort hier)

Also die Stringliteral wäre so etwas wie: "Service-Version 1.2.35.564 läuft"

Ich hatte die 1.2.35.564 aus diesem wörtlichen zu analysieren. Ein Stichwort von @ajborley, meine regex ist wie folgt:

(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)

Ein kleines C # Schnipsel dies zu testen sieht aus wie folgt:

void Main()
{
    Regex regEx = new Regex(@"(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)", RegexOptions.Compiled);

    Match version = regEx.Match("The Service SuperService 2.1.309.0) is Running!");
    version.Value.Dump("Version using RegEx");   // Prints 2.1.309.0        
}

Ich neige dazu, mit Split-Vorschlag zustimmen.

Ive erstellt einen "Tester" für Ihr Problem in Perl

#!/usr/bin/perl -w


@strings = ( "1.2.3", "1.2.*", "1.*","*" );

%regexp = ( svrist => qr/(?:(\d+)\.(\d+)\.(\d+)|(\d+)\.(\d+)|(\d+))?(?:\.\*)?/,
            onebyone => qr/^(\d+\.)?(\d+\.)?(\*|\d+)$/,
            greg => qr/^(\*|\d+(\.\d+){0,2}(\.\*)?)$/,
            vonc => qr/^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$/,
            ajb => qr/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/,
            jrudolph => qr/^(((\d+)\.)?(\d+)\.)?(\d+|\*)$/
          );

  foreach my $r (keys %regexp){
    my $reg = $regexp{$r};
    print "Using $r regexp\n";
foreach my $s (@strings){
  print "$s : ";

    if ($s =~m/$reg/){
    my ($main, $maj, $min,$rev,$ex1,$ex2,$ex3) = ("any","any","any","any","any","any","any");
    $main = $1 if ($1 && $1 ne "*") ;
    $maj = $2 if ($2 && $2 ne "*") ;
    $min = $3 if ($3 && $3 ne "*") ;
    $rev = $4 if ($4 && $4 ne "*") ;
    $ex1 = $5 if ($5 && $5 ne "*") ;
    $ex2 = $6 if ($6 && $6 ne "*") ;
    $ex3 = $7 if ($7 && $7 ne "*") ;
    print "$main $maj $min $rev $ex1 $ex2 $ex3\n";

  }else{
  print " nomatch\n";
  }
  }
print "------------------------\n";
}

Stromausgang:

> perl regex.pl
Using onebyone regexp
1.2.3 : 1. 2. 3 any any any any
1.2.* : 1. 2. any any any any any
1.* : 1. any any any any any any
* : any any any any any any any
------------------------
Using svrist regexp
1.2.3 : 1 2 3 any any any any
1.2.* : any any any 1 2 any any
1.* : any any any any any 1 any
* : any any any any any any any
------------------------
Using vonc regexp
1.2.3 : 1.2. 3 any any any any any
1.2.* : 1. 2 .* any any any any
1.* : any any any 1 any any any
* : any any any any any any any
------------------------
Using ajb regexp
1.2.3 : 1 2 3 any any any any
1.2.* : 1 2 any any any any any
1.* : 1 any any any any any any
* : any any any any any any any
------------------------
Using jrudolph regexp
1.2.3 : 1.2. 1. 1 2 3 any any
1.2.* : 1.2. 1. 1 2 any any any
1.* : 1. any any 1 any any any
* : any any any any any any any
------------------------
Using greg regexp
1.2.3 : 1.2.3 .3 any any any any any
1.2.* : 1.2.* .2 .* any any any any
1.* : 1.* any .* any any any any
* : any any any any any any any
------------------------

Dies sollte funktionieren, was Sie vereinbart. Es hängt von der Wild Card Position und ist eine verschachtelte regex:

^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$

http://imgur.com/3E492.png

Ich habe eine Menge Antworten gesehen, aber ... ich habe einen neuen. Es funktioniert für mich zumindest. Ich habe eine neue Beschränkung hinzugefügt. Die Versionsnummern können nicht gestartet werden (Haupt-, Neben- oder Patch) mit irgendwelchen von anderen gefolgt Nullen.

  

01.0.0 ist nicht gültig   1.0.0 ist gültig   10.0.10 gültig   1.0.0000 ist nicht gültig

^(?:(0\\.|([1-9]+\\d*)\\.))+(?:(0\\.|([1-9]+\\d*)\\.))+((0|([1-9]+\\d*)))$

Es ist in einem früheren basiert. Aber ich sehe diese Lösung besser ... für mich;)

Genießen Sie !!!

Ein weiterer Versuch:

^(((\d+)\.)?(\d+)\.)?(\d+|\*)$

Das gibt die drei Teile in Gruppen 4,5,6 ABER: Sie sind nach rechts ausgerichtet. So ist die erste Nicht-Null eines von 4,5 oder 6 gibt das Versionsfeld.

  • 1.2.3 gibt 1,2,3
  • 1.2. * Gibt 1,2, *
  • 1.2 gibt null, 1,2
  • *** gibt null, null, *
  • 1. * gibt null, 1, *
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$

Vielleicht ein prägnant man könnte sein:

^(?:(\d+)\.){0,2}(\*|\d+)$

Dies kann dann zu 1.2.3.4.5 verbessert werden. * Oder eingeschränkt genau mit X.Y.Z * oder {2} anstelle von {0,2}

hatte ich eine Anforderung / Spiel für Versionsnummern zu suchen, die Maven-Konvention oder auch nur einzelne Ziffer folgt. Aber kein Qualifier in jedem Fall. Es war eigenartig, es hat mir Zeit dann ich kam auf diese:

'^[0-9][0-9.]*$'

Dies stellt sicher, dass die Version,

  1. beginnt mit einer Ziffer
  2. kann eine beliebige Anzahl von Ziffern haben
  3. Nur Ziffern und '' sind erlaubt

Ein Nachteil ist, dass Version kann sogar am Ende mit ‚‘ Aber es kann unbestimmte Länge von Version umgehen (verrückt Versionierung, wenn Sie es nennen wollen, dass)

Spiele:

  • 1.2.3
  • 1.09.5
  • 3.4.4.5.7.8.8.
  • 23.6.209.234.3

Wenn Sie nicht unzufrieden mit ‚‘ können Sie mit endswith Logik

kombinieren kann enden,
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$

Hat Ihr 6 ersten Beispiele genau übereinstimmen, und lehnt die 4 anderen

  • Gruppe 1: Haupt- oder major.minor oder '*'
  • Gruppe 2, wenn vorhanden: minor oder *
  • Gruppe 3, wenn vorhanden ist: *

Sie können entfernen '(? Ms)'
Ich habe es auf diese regexp, um anzuzeigen, auf mehreren Linien aufgebracht werden durch QuickRex

Das paßt 1.2.3. * Zu

  

^ (* |..? \ D + (\ d +) {0,2} (*)) $

Ich würde vorschlagen, die weniger elegant:

(* | \ d + (\ d +) (*).?.?) |.. \ D + \ d + \ d +)

Beachten Sie regexp sind gierig, wenn Sie also nur innerhalb der Versionsnummer String suchen und nicht in einem größeren Text, verwenden Sie ^ und $ markieren Beginn und Ende der Zeichenfolge. Die regexp von Greg scheint gut zu funktionieren (nur gab ihm einen schnellen Versuch in meinem Lektor), aber abhängig von Ihrer Bibliothek / Sprache kann der erste Teil noch die „*“ in den falschen Versionsnummern übereinstimmen. Vielleicht etwas, was ich bin fehlt, da ich nicht Regexp für ein Jahr oder so verwendet haben.

Dies sollte sicherstellen, dass Sie nur korrekte Versionsnummern finden:

^ (\ * |..? \ D + (\ \ d +) * (\ \ *)) $

edit: eigentlich greg fügte sie bereits und verbessert auch seine Lösung, ich bin zu langsam:)

Es scheint ziemlich schwer, einen regulären Ausdruck zu haben, die genau das tun, was Sie wollen (dh akzeptiert nur die Fälle, die Sie benötigen und verwerfen alle andere und Rückkehr einige Gruppen für die drei Komponenten). Ich habe es zu versuchen und kommen mit dieser:

^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$

IMO (Ich habe ausführlich nicht getestet) dies als Prüfung für die Eingabe funktionieren soll, aber das Problem ist, dass dieser regex nicht bietet eine Möglichkeit, die Komponenten des Abrufens. Dafür müssen Sie noch eine Spaltung auf Zeit tun.

Diese Lösung ist nicht all-in-one, aber die meiste Zeit in der Programmierung braucht es nicht zu. Natürlich hängt dies von anderen Einschränkungen, die Sie in Ihrem Code haben könnten.

Die Angabe XSD Elemente:

<xs:simpleType>
    <xs:restriction base="xs:string">
        <xs:pattern value="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(\..*)?"/>
    </xs:restriction>
</xs:simpleType>

Meine Meinung zu diesem Thema, als gute Übung - vparse , die ein winzige Quelle , mit einer einfachen Funktion:

function parseVersion(v) {
    var m = v.match(/\d*\.|\d+/g) || [];
    v = {
        major: +m[0] || 0,
        minor: +m[1] || 0,
        patch: +m[2] || 0,
        build: +m[3] || 0
    };
    v.isEmpty = !v.major && !v.minor && !v.patch && !v.build;
    v.parsed = [v.major, v.minor, v.patch, v.build];
    v.text = v.parsed.join('.');
    return v;
}

Eine weitere Lösung:

^[1-9][\d]*(.[1-9][\d]*)*(.\*)?|\*$
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top