Pregunta

Tengo un número de versión de la siguiente forma:

versión.de liberación.modificación

donde versión, la versión y la modificación son un conjunto de dígitos o el '*' carácter comodín.Además, cualquiera de estos números (y los anteriores .) puede ser que falte.

Por tanto, las siguientes son válidos y analizar como:

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

Pero estos no son válidos:

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

¿Alguien puede proporcionarme un no muy compleja expresión regular para validar y recuperar la liberación, la versión y la modificación de los números?

¿Fue útil?

Solución

Me gustaría expresar el formato como:

"1-3 separados por puntos componentes, cada uno numérico, excepto que el último puede ser *"

Como una regexp, que es:

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

[Editar para agregar:esta solución es una manera concisa para validar, pero se ha señalado que la extracción de los valores requiere trabajo adicional.Es una cuestión de gusto si lidiar con este complicando la regexp, o mediante el procesamiento de la concordancia grupos.

En mi solución, los grupos de captura de la "." los caracteres.Esto se puede resolver con el uso de la no-grupos de captura como en ajborley la respuesta.

También, el de más a la derecha del grupo de captura de la última componente, incluso si hay menos de tres componentes, y así, por ejemplo, una entrada de dos componentes resultados en la primera y la última grupos de la captura y el medio indefinido.Creo que esto puede ser tratado por no codicioso de los grupos donde compatibles.

Código en Perl para abordar ambas cuestiones después de la regexp podría ser algo como esto:

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

Que no es realmente más corta que la división en "." ]

Otros consejos

Uso de expresiones regulares (regex y ahora tiene dos problemas. Me gustaría dividir la cosa en puntos ("."), a continuación, asegúrese de que cada parte es un comodín o un conjunto de dígitos (regex es perfecto ahora).Si la cosa es válida, que acaba de volver correcta fragmento de la división.

Esto podría funcionar:

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

En el nivel superior, "*" es un caso especial de una tarjeta de número de versión.En caso contrario, comienza con un número.A continuación, hay cero, uno, o dos ".nn" secuencias, seguido por un facultativo ".*".Esta expresión sería aceptar 1.2.3.* que puede o no puede ser permitido en su aplicación.

El código para recuperar la coincidencia de las secuencias, especialmente la (\.\d+){0,2} parte, dependerá de la particular expresión de la biblioteca.

Gracias por todas las respuestas!Esto es as :)

Basado en OneByOne la respuesta (que parecía el más sencillo para mí), he añadido algunos de los grupos de captura (el" (?:' partes - gracias a VonC para presentarme a la no captura de los grupos!), por lo que los grupos que hacer la captura de sólo contener los dígitos o el carácter*.

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

Muchas gracias a todos!

No sé qué plataforma estás en pero .NETA que hay en el Sistema.La versión de la clase que analicen "n.n.n.n" números de versión para usted.

Mis 2 centavos:Yo tenía este escenario:Tuve que analizar los números de versión de un literal de cadena.(Sé que esto es muy diferente de la pregunta original, pero googleando para encontrar una expresión regular para analizar el número de versión mostró este hilo en la parte superior, por lo que la adición de esta respuesta aquí)

Así, la cadena literal sería algo como:"La versión del servicio de 1.2.35.564 está funcionando!"

Tuve que analizar la 1.2.35.564 de este literal.Tomando el ejemplo de @ajborley, mi expresión es la siguiente:

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

Una pequeña C# fragmento de la prueba de esto se ve como la siguiente:

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        
}

Tiendo a estar de acuerdo con la división propuesta.

He creado un "tester" para su problema en 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";
}

Salida de corriente:

> 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
------------------------

Esto debería funcionar para lo que se estipula.Se basa en el wild card de la posición y es un anidada regex:

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

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

He visto un montón de respuestas, pero...tengo una nueva.Funciona al menos para mí.He añadido una nueva restricción.Los números de versión no se puede iniciar (mayor, menor o parche) con ceros a la que siguieron otras.

01.0.0 no es válido 1.0.0 es válido 10.0.10 es válido 1.0.0000 no es válido

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

Se basa en una anterior.Pero veo que esta solución mejor...para mí ;)

Disfrutar!!!

Otro intento:

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

Esto le da a las tres partes en grupos 4,5,6 PERO:Están alineados a la derecha.Así que la primera no nulos, uno de 4,5 o 6 da la versión de campo.

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

Tal vez una forma más concisa podría ser :

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

Esto puede ser mejorado para 1.2.3.4.5.* o restringido exactamente a X. Y. Z el uso de * o {2} en lugar de {0,2}

Tuve un requisito para la búsqueda y coinciden con los números de versión, que sigue maven convención o incluso de un solo dígito.Pero no hay calificador en cualquier caso.Era peculiar, me tomó tiempo entonces se me ocurrió esto:

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

Esto asegura que la versión,

  1. Comienza con un dígito
  2. Puede tener cualquier número de dígitos
  3. Sólo dígitos y '.' están permitidos

Un inconveniente es que la versión que incluso puede terminar con '.' Pero se puede manejar de duración indefinida de la versión (loco control de versiones si usted quiere llamarlo así)

Partidos:

  • 1.2.3
  • 1.09.5
  • 3.4.4.5.7.8.8.
  • 23.6.209.234.3

Si usted no está satisfecho con '.' final, puede ser que usted puede combinar con endswith lógica

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

No coinciden exactamente con sus 6 primeros ejemplos, y rechaza a los otros 4

  • grupo 1:grandes o importantes.menor o '*'
  • grupo 2 si existe:menor de edad o *
  • grupo 3 si existe:*

Usted puede quitar" (?ms)'
Yo lo he utilizado para indicar a este regexp para ser aplicado en múltiples líneas a través de QuickRex

Esto coincide con 1.2.3.* demasiado

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

Me gustaría proponer la menos elegante:

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

Tenga en cuenta regexp son codiciosos, así que si usted está buscando en el número de versión de la cadena y no dentro de una más grande de texto, utilice ^ y $ para marcar el inicio y final de la cadena.La regexp de Greg parece funcionar bien (sólo le dio un rápido probar en mi editor), pero dependiendo de su biblioteca/idioma la primera parte todavía puede coincidir con el "*" en la versión incorrecta de los números.Tal vez me estoy perdiendo algo, como no lo he usado Regexp para un año o así.

Esto debe asegurarse de que sólo se puede encontrar la versión correcta de los números:

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

editar:en realidad greg agregado ya, e incluso mejorado su solución, soy demasiado lento :)

Parece bastante difícil tener una expresión regular que hace exactamente lo que usted desea (es decir,aceptar sólo los casos que usted necesita y rechazar todos otros y retorno de algunos grupos para los tres componentes).He de intentarlo y llegar a esta:

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

La OMI (no lo he probado mucho) esto debería funcionar bien como un validador para la entrada, pero el problema es que esta expresión no ofrece una manera de recuperar los componentes.Para que usted todavía tiene que hacer un split en el período.

Esta solución no es todo-en-uno, pero la mayoría de las veces en la programación no es necesario.Por supuesto, esto depende de otras restricciones que pueda tener en su código.

La especificación de elementos XSD:

<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>

Mi opinión sobre esto, como un buen ejercicio vparse, que tiene un pequeña fuente, con una simple función:

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;
}

Uno más de la solución:

^[1-9][\d]*(.[1-9][\d]*)*(.\*)?|\*$
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top