比较版本号的最佳灵活方法是什么?

发布于 2024-08-23 13:43:58 字数 620 浏览 8 评论 0原文

我正在使用一个脚本来比较已安装和可用应用程序的版本号。通常,我会使用简单的比较运算符。由于我是在 PHP 5.3 环境中构建此应用程序,因此我考虑使用 version_compare(),但这似乎并不像我希望的那样完全满足我的需求。

我正在比较的版本字符串可以遵循多种格式,但到目前为止我遇到的格式是:

  • “2.6.18-164.6.1.el5”与“2.6.18-92.1.13.el5”
  • “4.3p2”与“5.1” p1'
  • '5.1.6' 与 '5.2.12'
  • '2.6.24.4-foo.bar.x.i386' 与 '2.4.21-40'

如您所见,确实没有一致的格式供我使用。

我考虑做的一件事是将每个版本字符串拆分为非数字字符,然后迭代结果数组并比较相对索引。但是,我不确定这是否是一个好方法,特别是在“2.6.24-4-foo.a.12.i386”与“2.6.24-4-foo.b.12”的情况下.i386'。

是否有任何经过充分测试的方法可以比较非常宽松的版本号(例如,特别是在 PHP 环境中)?

I am working with a script to compare version numbers for installed and available applications. I would, on a normal basis, use simple comparison operators. Since I am building this application in a PHP 5.3 environment, I have considered the use of version_compare(), but that doesn't seem to suit my needs as cleanly as I would like.

The version strings I am comparing can follow many formats, but those I have encountered thus far are:

  • '2.6.18-164.6.1.el5' versus '2.6.18-92.1.13.el5'
  • '4.3p2' versus '5.1p1'
  • '5.1.6' versus '5.2.12'
  • '2.6.24.4-foo.bar.x.i386' versus '2.4.21-40'

As you can see, there really is no consistent format for me to work with.

The one thing I considered doing was splitting each version string on the non-numeric characters, then iterating the resulting arrays and comparing relative indices. However, I'm not sure that would be a good way of doing it, especially in the case of '2.6.24-4-foo.a.12.i386' versus '2.6.24-4-foo.b.12.i386'.

Are there any well-tested methods of comparing very loose version numbers such as this, specifically in a PHP environment?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

落墨 2024-08-30 13:43:58

按符号拆分(请参阅 preg_split)并以数字方式比较每个元素(如果两者都是数字)或使用字符串比较(当两者都是字母数字时)适用于您的示例:

    '2.6.18-164.6.1.el5' > '2.6.18-92.1.13.el5'
    2  6  18  164 6  1  e15
    2  6  18  92  1  13 e16 // higher
              ^ 

    '4.3p2' < '5.1p1'
    4 3 p2
    5 1 p1 // higher
    ^

    '5.1.6' < '5.2.12'
     5  1  6
     5  2  12 // higher
        ^

    '2.6.24.4-foo.bar.x.i386' > '2.4.21-40'
     2  6  24  4   foo  bar  x  i386 // higher
     2  4  21  40  ---  ---  -  ---- 
        ^

它可能会失败的是像 5.2-alpha-foo 与 5.2.49.4-beta-bar 这样的版本,您必须比较纯数字带有字母数字子字符串的子字符串:

    5.2-alpha-foo > 5.2.49.9.-beta-bar
    5  2  alpha  foo ----  ---  // wrong - ascii 65(a) vs 52(4)
    5  2  49     4   beta  bar
          ^

每当您将纯数字子字符串与字母数字子字符串进行比较时,您都可以通过将字母数字字段视为 0 来解决此问题。

Splitting by symbol (see preg_split) and comparing each element numerically (if both are numeric) or using string comparison (when both are alphanumeric) works for your examples:

    '2.6.18-164.6.1.el5' > '2.6.18-92.1.13.el5'
    2  6  18  164 6  1  e15
    2  6  18  92  1  13 e16 // higher
              ^ 

    '4.3p2' < '5.1p1'
    4 3 p2
    5 1 p1 // higher
    ^

    '5.1.6' < '5.2.12'
     5  1  6
     5  2  12 // higher
        ^

    '2.6.24.4-foo.bar.x.i386' > '2.4.21-40'
     2  6  24  4   foo  bar  x  i386 // higher
     2  4  21  40  ---  ---  -  ---- 
        ^

Where it potentially falls down is a version like 5.2-alpha-foo vs 5.2.49.4-beta-bar where you must compare a purely numeric sub-string with an alphanumeric sub-string:

    5.2-alpha-foo > 5.2.49.9.-beta-bar
    5  2  alpha  foo ----  ---  // wrong - ascii 65(a) vs 52(4)
    5  2  49     4   beta  bar
          ^

You could solve this by treating the alphanumeric field as 0 any time you have a purely numeric sub-string compared against an alphanumeric sub string.

迷爱 2024-08-30 13:43:58

作为参考,rpm 比较版本字符串如下所示:

  • 拆分所有非字母数字字符
  • 将连续数字字符分组在一起,将所有非数字字符分组在一起(即 1.12.ab002 拆分为 1、12、ab、002)
  • 比较每个组从左到右
    • 如果两个版本都有数字组,则将它们作为数字进行比较(即 1 = 001 且 12 > 5)
    • 如果其中一个是非数字组,则执行简单的字符串比较
  • 第一个不等于比较的结果
  • 较长版本被认为是更大的(即 1.2.3 < 1.2.3.0 和 alp < alpha)

这有缺陷: 1.2.3rc1 > 1.2.3 和1.2.3alpha > 1.2.3 可能不正确

For reference rpm compare version strings something like this:

  • Split on all non-alpha-numeric character
  • Group consecutive numeric characters together and all non-numeric characters together (i.e. 1.12.ab002 is split into 1, 12, ab, 002)
  • Compare each group left to right
    • if both versions have numeric group they are compared as numbers (i.e. 1 = 001 and 12 > 5)
    • if either is a non-numeric group a simple string comparison is performed
  • The first non-equal comparison is the result
  • Longer versions are considered greater (i.e. 1.2.3 < 1.2.3.0 and alp < alpha)

This has flaws: 1.2.3rc1 > 1.2.3 and 1.2.3alpha > 1.2.3 which may not be right

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文