c++oding="utf-8" ?>
有效的 semver 字符串结构为:vmajor.minor.patch(v可选),后接至多一个-prerelease(由点分隔的非空标识符,每个标识符不得以数字开头且若全数字则无前导零),再接至多一个+build(仅含ascii字母、数字、.、+,且+在-后)。

什么是有效的 SemVer 字符串结构
一个符合 SemVer 2.0.0 的字符串必须严格满足:vMAJOR.MINOR.PATCH(可选前导 v),后接可选的 -PRERELEASE 和/或 +BUILD。注意:不是“看起来像版本号”就行,比如 1.2、1.2.3.4、1.2.3-rc1.0 都是非法的。
关键约束包括:
-
MAJOR、MINOR、PATCH必须是**非负整数,且不能有前导零**(0合法,01不合法) -
PRERELEASE(如alpha.1)只能由 ASCII 字母、数字和连字符-组成,每个标识符**不能为空,也不能以数字开头**(1alpha合法,alpha1合法,但1单独作为标识符合法,01不合法) -
BUILD(如+20240501.1)只允许 ASCII 字母、数字和.、+,且必须以+开头 -
-和+最多各出现一次,且-必须在+前面
用正则表达式快速初筛(C++11 及以上)
正则能高效过滤掉明显非法格式,但 C++ 标准库的 std::regex 对 Unicode 和某些边界行为支持较弱,且无法校验“无前导零”这类逻辑。建议仅用于初步分词和结构检查。
推荐使用这个 PCRE 风格兼容的正则(需转义为 C++ 字符串字面量):
^v?(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.-]*))?$
实际使用时注意:
- 用
std::regex_match(s, re, std::regex_constants::ECMAScript)全匹配,不要用search - 必须启用
ECMAScript模式(默认可能不支持\d等) - 匹配成功后仍需对捕获组做额外校验:比如检查
PRERELEASE中每个点分段是否为空、是否数字开头等 - MSVC 的
std::regex在 debug 模式下性能极差,生产环境慎用;Clang/libc++ 和 GCC libstdc++ 表现更稳定
手写解析器才是可靠方案(推荐)
真正健壮的判断必须拆解并逐段验证。核心思路是:按 .、-、+ 切分 → 分别校验三段 → 再校验每段内部规则。以下关键点容易出错:
- 先跳过可选的
v前缀,但要确保它**只出现在开头**(av1.2.3应失败) -
MAJOR.MINOR.PATCH必须恰好三段,每段用std::stoi转换时捕获异常,并比对原始字符串长度与转换后to_string是否一致(检测前导零) - 遇到
-后,把后续内容按.切分为 prerelease identifiers,对每个 identifier:- 长度 > 0
- 若全为数字,则不能有前导零(即不能是
"00"或"01") - 若含字母,则首字符不能是数字(
"1abc"非法,"abc1"合法)
- 遇到
+后,build metadata 只需检查字符集([0-9a-zA-Z.-]),且不能为空
示例片段(校验一段数字字符串是否无前导零):
bool has_no_leading_zero(const std::string& s) {
return s.empty() || s == "0" || s[0] != '0';
}
要不要依赖第三方库?
如果项目已用 cmake 且能接受额外依赖,libsemver(C 实现)或 semver-parser(header-only C++)确实省心。但要注意:
-
libsemver的 C API 需手动管理内存,且不严格区分v1.2.3和1.2.3(它认为都合法,但 SemVer 规范明确允许可选v前缀,所以两者都应接受) - 多数轻量 parser 不校验 prerelease identifier 的“首字符非数字”规则,会把
1alpha当作合法 —— 这违反 SemVer spec - 如果你只需要判断合法性(而非后续比较),手写 150 行左右的解析器反而更可控、无依赖、易调试
真正难的不是切分,而是把 spec 里那些“不得”“必须”“仅限”条件一一手动落实。尤其 prerelease identifier 的规则,文档描述拗口,实操中极易漏判。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











