严格的SemVer字符串格式必须为“MAJOR.MINOR.PATCH”或其扩展形式(含预发布标签或构建元数据),且须严格遵循字符集、顺序及语义约束,如禁止前导零、空标识符、非法字符等;正则仅作初步校验,完整验证需结合语义解析或专业库(如semvercpp)。

什么是严格的 SemVer 字符串格式
严格符合 SemVer 2.0.0 的字符串必须满足:形如 "MAJOR.MINOR.PATCH"(如 "1.2.3"),或带预发布标签("1.2.3-alpha.1"),或带构建元数据("1.2.3+20240101"),且三者组合需遵循明确顺序和字符集限制。常见误判点是把 "1.2"、"v1.2.3"、"1.2.3.4" 当作合法版本——它们都不符合规范。
用正则表达式做初步校验(C++11 及以上)
std::regex 可以快速筛掉明显非法输入,但要注意 C++ 标准库 regex 对 Unicode 和某些边界情况支持有限,仅适合 ASCII 场景下的严格 SemVer。推荐使用以下模式:
std::regex semver_regex(R"(^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$)");
关键点:
- 必须用原始字符串字面量(
R"(...)")避免转义混乱 - 预发布字段(
-xxx)和构建字段(+xxx)均为可选,但若存在,顺序不可颠倒 - 预发布标识符不能为空(
"1.2.3-"非法),构建元数据同理("1.2.3+"非法) -
std::regex_match要求完全匹配,不能用search
手动解析并验证语义约束(绕过 regex 缺陷)
正则无法检查数字是否溢出(如 "99999999999999999999.0.0")、预发布标识符是否含非法字符(如空格、下划线)、或构建元数据是否含斜杠等细节。建议在 regex 匹配成功后,再做结构化解析:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 用
std::stoi解析主版本号,捕获std::out_of_range异常(SemVer 不限制位数,但实际场景中整数溢出即应视为非法) - 预发布字段按
'.'分割后,每个标识符必须非空、且只含 ASCII 字母、数字、'-'(不允许'_'或' ') - 构建字段同理,但允许任意 ASCII 字符(除控制字符外),不过实践中建议限制为字母、数字、
'.'、'-' - 检查是否有连续点号(
"1.2.3-alpha..1")或结尾点号("1.2.3-alpha.")——这些 regex 无法捕获
推荐:用成熟第三方库(如 semvercpp)
自己实现易漏边界情况,比如 "1.2.3-01.02" 中的前导零(SemVer 明确禁止预发布标识符以数字开头时带前导零)。semvercpp 库提供 semver::version::parse(),会严格按规范校验并抛出异常。使用方式简洁:
try {
auto v = semver::version::parse("1.2.3-alpha.1+build.123");
} catch (const std::invalid_argument& e) {
// e.what() 会说明具体哪条规则违反,比如 "invalid prerelease identifier: '01'"
}
注意:semvercpp 不支持构建元数据比较逻辑,仅做解析和基本验证;若需完整语义比较(如 is_prerelease()、operator<),需确认所用版本是否启用该功能。
真正难的不是匹配格式,而是理解 SemVer 规范里那些“看似宽松实则苛刻”的细节——比如预发布标识符的排序规则、构建元数据不参与比较、主版本号为 0 时的特殊含义。这些靠正则根本覆盖不到,必须依赖语义解析器或人工逐条核对。

















