Tengo un número de versión del siguiente formulario:
version.release.modification
donde la versión, el lanzamiento y la modificación son un conjunto de dígitos o el carácter comodín '*'. Además, es posible que falte alguno de estos números (y los anteriores).
Entonces, los siguientes son válidos y se analizan 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 una expresión regular no demasiado compleja para validar y recuperar los números de lanzamiento, versión y modificación?
regex
versioning
Andrew Borley
fuente
fuente
Respuestas:
Expresaría el formato como:
Como expresión regular, eso es:
^(\d+\.)?(\d+\.)?(\*|\d+)$
[Editar para agregar: esta solución es una forma concisa de validar, pero se ha señalado que extraer los valores requiere trabajo adicional. Es cuestión de gustos si tratar con esto complicando la expresión regular o procesando los grupos emparejados.
En mi solución, los grupos capturan la
"."
personajes. Esto se puede solucionar utilizando grupos que no capturan como en la respuesta de ajborley.Además, el grupo más a la derecha capturará el último componente, incluso si hay menos de tres componentes, por lo que, por ejemplo, una entrada de dos componentes da como resultado la captura del primer y último grupo y el del medio indefinido. Creo que esto puede ser abordado por grupos que no sean codiciosos si reciben apoyo.
El código Perl para tratar ambos problemas después de la expresión regular podría ser algo como esto:
@version = (); @groups = ($1, $2, $3); foreach (@groups) { next if !defined; s/\.//; push @version, $_; } ($major, $minor, $mod) = (@version, "*", "*");
Lo que en realidad no es más corto que dividirse
"."
]fuente
Use regex y ahora tiene dos problemas. Dividiría la cosa en puntos ("."), Luego me aseguraría de que cada parte sea un comodín o un conjunto de dígitos (la expresión regular es perfecta ahora). Si la cosa es válida, devuelve la parte correcta de la división.
fuente
Esto podría funcionar:
^(\*|\d+(\.\d+){0,2}(\.\*)?)$
En el nivel superior, "*" es un caso especial de un número de versión válido. De lo contrario, comienza con un número. Luego hay cero, una o dos secuencias ".nn", seguidas de un ". *" Opcional. Esta expresión regular aceptaría 1.2.3. * Que puede o no estar permitido en su aplicación.
El código para recuperar las secuencias coincidentes, especialmente la
(\.\d+){0,2}
parte, dependerá de su biblioteca de expresiones regulares en particular.fuente
¡Gracias por todas las respuestas! Esto es as :)
Basado en la respuesta de OneByOne (que me pareció la más simple), agregué algunos grupos que no capturan (las partes '(?:', ¡Gracias a VonC por presentarme a los grupos que no capturan!), Por lo que los grupos que capturan solo contener los dígitos o el carácter *.
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
¡Muchas gracias a todos!
fuente
(\*|\d+)
no con el primer^(?:(\d+)\.)?
grupo.Mis 2 centavos: tuve 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 buscar en Google para encontrar una expresión regular para analizar el número de versión mostró este hilo en la parte superior, así que agregue esta respuesta aquí)
Entonces, la cadena literal sería algo como: "¡La versión de servicio 1.2.35.564 se está ejecutando!"
Tuve que analizar el 1.2.35.564 de este literal. Siguiendo el ejemplo de @ajborley, mi expresión regular es la siguiente:
(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)
Un pequeño fragmento de C # para probar esto se ve a continuación:
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 }
fuente
X.Y.Z
(por lo tanto, exactamente tres partes), donde X e Y deben ser números enteros no negativos y no ceros iniciales adicionales. Ver semver.org .No sé en qué plataforma estás, pero en .NET existe la clase System.Version que analizará los números de versión "nnnn" por ti.
fuente
Tiendo a estar de acuerdo con la sugerencia dividida.
He creado un "probador" 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 ------------------------
fuente
Esto debería funcionar para lo que estipuló. Depende de la posición del comodín y es una expresión regular anidada:
^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$
fuente
He visto muchas respuestas, pero ... tengo una nueva. Funciona para mí al menos. Agregué una nueva restricción. Los números de versión no pueden comenzar (mayor, menor o parche) con ceros seguidos de otros.
^(?:(0\\.|([1-9]+\\d*)\\.))+(?:(0\\.|([1-9]+\\d*)\\.))+((0|([1-9]+\\d*)))$
Está basado en uno anterior. Pero veo esta solución mejor ... para mí;)
¡¡¡Disfrutar!!!
fuente
Otro intento:
^(((\d+)\.)?(\d+)\.)?(\d+|\*)$
Esto da las tres partes en grupos 4, 5, 6 PERO: Están alineadas a la derecha. Entonces, el primer no nulo de 4,5 o 6 da el campo de versión.
fuente
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
Quizás uno más conciso podría ser:
^(?:(\d+)\.){0,2}(\*|\d+)$
Esto luego se puede mejorar a 1.2.3.4.5. * O restringir exactamente a XYZ usando * o {2} en lugar de {0,2}
fuente
Tenía el requisito de buscar / hacer coincidir los números de versión, que siguen la convención de maven o incluso un solo dígito. Pero no calificativo en ningún caso. Fue peculiar, me tomó tiempo y luego se me ocurrió esto:
'^[0-9][0-9.]*$'
Esto asegura que la versión,
Un inconveniente es que la versión puede incluso terminar con '.' Pero puede manejar una duración indefinida de la versión (versiones locas si quieres llamarlo así)
Partidos:
Si no está satisfecho con '.' terminando, puede ser que puedas combinar con fines con lógica
fuente
(\d+)(.\d+)*
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$
Coincide exactamente con sus 6 primeros ejemplos y rechaza los otros 4
Puede eliminar '(? Ms)'
Lo usé para indicar a esta expresión regular que se aplicará en líneas múltiples a través de QuickRex
fuente
Esto también coincide con 1.2.3. *
Propondría lo menos elegante:
(* | \ d + (. \ d +)? (. *)?) | \ d +. \ d +. \ d +)
fuente
Tenga en cuenta que las expresiones regulares son codiciosas, por lo que si solo está buscando dentro de la cadena del número de versión y no dentro de un texto más grande, use ^ y $ para marcar el inicio y el final de su cadena. La expresión regular de Greg parece funcionar bien (solo lo probé rápidamente en mi editor), pero dependiendo de su biblioteca / idioma, la primera parte aún puede coincidir con el "*" dentro de los números de versión incorrectos. Quizás me esté perdiendo algo, ya que no he usado Regexp durante un año más o menos.
Esto debería asegurarse de que solo pueda encontrar los números de versión correctos:
^ (\ * | \ d + (\. \ d +) * (\. \ *)?) $
editar: en realidad, Greg ya los agregó e incluso mejoró su solución, soy demasiado lento :)
fuente
Parece bastante difícil tener una expresión regular que haga exactamente lo que desea (es decir, aceptar solo los casos que necesita y rechazar todos los demás y devolver algunos grupos para los tres componentes). Lo intenté y se me ocurrió esto:
^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$
En mi opinión (no lo he probado ampliamente), esto debería funcionar bien como validador de la entrada, pero el problema es que esta expresión regular no ofrece una forma de recuperar los componentes. Para eso todavía tienes que dividir 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.
fuente
Especificar 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>
fuente
Mi opinión sobre esto, como un buen ejercicio: vparse , que tiene una fuente pequeña , con una función simple:
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; }
fuente
Para analizar los números de versión que siguen estas reglas: - Son solo dígitos y puntos - No pueden comenzar ni terminar con un punto - No pueden ser dos puntos juntos
Este me hizo el truco.
^(\d+)((\.{1}\d+)*)(\.{0})$
Los casos válidos son:
1, 0,1, 1,2,1
fuente
Una solución más:
^[1-9][\d]*(.[1-9][\d]*)*(.\*)?|\*$
fuente
A veces, los números de versión de menor importancia pueden contener información alfanumérica (por ejemplo 1.2.0b o 1.2.0-beta ). En este caso, estoy usando esta expresión regular:
([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})
fuente
Encontré esto y me funciona:
/(\^|\~?)(\d|x|\*)+\.(\d|x|\*)+\.(\d|x|\*)+
fuente