Validador de versão SemVer
Digite uma versão semântica (ex.: 1.4.2-beta.1+build.5), compare com outra e ordene listas de versões.
Processamento local: nada do que você digita sai do seu navegador.
Como usar
Digite uma versão no campo A para validá-la e ver cada parte (MAJOR, MINOR, PATCH, pré-lançamento e build). Preencha também o campo B para saber qual das duas é maior. Na caixa de baixo, cole várias versões (uma por linha) para ordená-las da menor para a maior; as inválidas são listadas com o motivo.
Regras do SemVer 2.0.0
- Formato
MAJOR.MINOR.PATCH, com números inteiros sem zero à esquerda. - Pré-lançamento vem após hífen (
1.0.0-rc.1) e tem precedência menor que a versão final. - Metadados de build vêm após
+e são ignorados na comparação. - Identificadores numéricos do pré-lançamento são comparados como números (
beta.2 < beta.11) e valem menos que os alfanuméricos. - O prefixo
v(como emv1.2.3) é comum em tags do Git, mas não faz parte da especificação.
Como implementar em código
Exemplos prontos para usar no seu projeto.
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
function parseSemver(v) {
const m = SEMVER.exec(v);
if (!m) return null;
return { major: +m[1], minor: +m[2], patch: +m[3], pre: m[4] ?? null, build: m[5] ?? null };
}
console.log(parseSemver('1.4.2-beta.1+build.5')); // { major: 1, minor: 4, patch: 2, pre: 'beta.1', build: 'build.5' }
console.log(parseSemver('01.0.0')); // null (zero à esquerda)
console.log(parseSemver('v1.0.0')); // null (prefixo v)Para comparar e ordenar use o pacote npm semver (semver.compare, semver.sort).
import re
# Expressão regular oficial do SemVer 2.0.0 (semver.org)
SEMVER = re.compile(
r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$")
def parse_semver(v: str):
m = SEMVER.match(v)
if not m:
return None
major, minor, patch, pre, build = m.groups()
return {"major": int(major), "minor": int(minor), "patch": int(patch), "pre": pre, "build": build}
print(parse_semver("1.4.2-beta.1+build.5")) # {'major': 1, 'minor': 4, 'patch': 2, 'pre': 'beta.1', 'build': 'build.5'}
print(parse_semver("01.0.0")) # None
print(parse_semver("v1.0.0")) # NonePara comparar e ordenar use o pacote semver (semver.Version.parse).
package main
import (
"fmt"
"regexp"
)
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
var semver = regexp.MustCompile(`^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
func main() {
for _, v := range []string{"1.4.2-beta.1+build.5", "01.0.0", "v1.0.0"} {
m := semver.FindStringSubmatch(v)
if m == nil {
fmt.Println(v, "-> inválida")
continue
}
fmt.Printf("%s -> major=%s minor=%s patch=%s pre=%q build=%q\n", v, m[1], m[2], m[3], m[4], m[5])
}
}Para comparar versões use golang.org/x/mod/semver (exige o prefixo v) ou github.com/Masterminds/semver.
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
final semver = RegExp(
r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$");
void main() {
for (final v in ['1.4.2-beta.1+build.5', '01.0.0', 'v1.0.0']) {
final m = semver.firstMatch(v);
if (m == null) {
print('$v -> inválida');
} else {
print('$v -> major=${m[1]} minor=${m[2]} patch=${m[3]} pre=${m[4]} build=${m[5]}');
}
}
}Para comparar versões use o pacote pub_semver (Version.parse).
import java.util.regex.*;
public class SemverCheck {
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
static final Pattern SEMVER = Pattern.compile(
"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
public static void main(String[] args) {
for (String v : new String[]{"1.4.2-beta.1+build.5", "01.0.0", "v1.0.0"}) {
Matcher m = SEMVER.matcher(v);
if (!m.matches()) {
System.out.println(v + " -> inválida");
continue;
}
System.out.println(v + " -> major=" + m.group(1) + " minor=" + m.group(2) + " patch=" + m.group(3)
+ " pre=" + m.group(4) + " build=" + m.group(5));
}
}
}Para comparar versões use a biblioteca java-semver ou semver4j.
<?php
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
const SEMVER = '~^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$~';
function parseSemver(string $v): ?array {
if (!preg_match(SEMVER, $v, $m)) return null;
return ['major' => (int)$m[1], 'minor' => (int)$m[2], 'patch' => (int)$m[3],
'pre' => $m[4] ?? null, 'build' => $m[5] ?? null];
}
print_r(parseSemver('1.4.2-beta.1+build.5'));
var_dump(parseSemver('01.0.0')); // NULL
var_dump(parseSemver('v1.0.0')); // NULLPara comparar versões, version_compare() do PHP aceita a maioria dos formatos semânticos.
using System;
using System.Text.RegularExpressions;
class Program
{
// Expressão regular oficial do SemVer 2.0.0 (semver.org)
static readonly Regex Semver = new(
@"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$");
static void Main()
{
foreach (var v in new[] { "1.4.2-beta.1+build.5", "01.0.0", "v1.0.0" })
{
var m = Semver.Match(v);
if (!m.Success) { Console.WriteLine($"{v} -> inválida"); continue; }
Console.WriteLine($"{v} -> major={m.Groups[1]} minor={m.Groups[2]} patch={m.Groups[3]} pre={m.Groups[4]} build={m.Groups[5]}");
}
}
}Para comparar versões use o pacote NuGet Semver (SemVersion.Parse).
Perguntas frequentes
Por que v1.2.3 é considerada inválida?
A especificação SemVer não inclui o prefixo v. Muitas ferramentas o aceitam como conveniência, mas o formato oficial é 1.2.3. Retire o v para validar.
Duas versões que só diferem no build são iguais?
Na precedência sim: 1.0.0+a e 1.0.0+b são tratadas como equivalentes, pois a especificação manda ignorar os metadados de build ao comparar.
Qual versão é maior, 1.0.0-rc.1 ou 1.0.0?
1.0.0 é maior. Qualquer pré-lançamento tem precedência menor do que a versão normal correspondente.
Veja também
Precisa de um sistema ou app sob medida?
A VcInova desenvolve software, aplicativos e integrações para empresas de todo o Brasil.
Fale com a VcInova