正则表达式不能直接比较版本大小,但能精准提取semver各结构化成分;主次修订号转整数比较,预发布字段需拆解为标识符数组并按语义规则逐段比,构建元数据忽略,非标版本须预清洗。

正则表达式本身不能直接比较版本大小,但它能可靠地“切开”复杂版本号,把主版本、次版本、修订号、预发布标识、构建元数据等结构化成分精准分离出来——这是后续正确比较的前提。
先用正则提取核心段落
面对标准 SemVer(如 2.10.0-rc.3+20240501),推荐使用这个表达式:
^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$
- $1 $2 $3 分别捕获主、次、修订号(字符串,需转整数)
-
$4 是预发布字段(如
rc.3),为空表示稳定版 -
$5 是构建元数据(如
20240501),比较时直接忽略 - 非捕获组
(?:...)?确保可选部分不干扰编号顺序
预发布字段要再拆解才能排序
像 alpha.10 和 beta.2 不能当普通字符串比,得按语义规则逐段处理:
- 对 $4 再匹配
([0-9]+|[^\d.]+),得到标识符数组,例如beta.11.alpha→['beta', '11', 'alpha'] - 遍历该数组:纯数字转成整数比,其余按字典序比
- 遇到空字符串(如
..)应跳过,实际使用前建议先校验格式合法性
不同语言里怎么接续比较
正则只负责“分”,比较逻辑必须由宿主语言完成:
-
PHP 直接用
version_compare($v1, $v2),它已内置预发布优先级(alpha ),无需手动解析 - JavaScript 提取三段数字后转整数逐位比;若含预发布,需额外实现标识符序列归一化逻辑
-
Java 可将
$1 $2 $3解析为int[],再结合自定义Comparable处理预发布字段 - 所有语言都应丢弃 $5(构建元数据),它不影响语义优先级
应对现实中的非标写法
真实版本号常带前缀或杂项(如 v1.2.3、2023.04.15-release),需预清洗:
- 允许首尾空白:
^\s*(\d+)\.(\d+)\.(\d+) - 拒绝非法前导零:
(0|[1-9]\d*)替代\d+ - 提取干净主干:
preg_match('/^v?(\d+(?:\.\d+){2})/', $raw, $m)→ 得到1.2.3 - 对非 SemVer 格式(如日期型),先定位关键段再交由
version_compare或自定义逻辑











