Ruby 如何比较语义版本字符串?

How does Ruby compare semantic version strings?

我在比较 Ruby 字符串时注意到一些意外行为。我将在下面写:

2.3.1 :011 >   '5.6' >= '5.5'
  => true
2.3.1 :012 >   '5.6' >= '5.7'
  => false
2.3.1 :013 >   '5.6' >= '5.6.1'
  => false
2.3.1 :014 >   '5.6' <= '5.6.1'
  => true
2.3.1 :016 >   '4.6.1' <= '5.6'
  => true
2.3.1 :017 >   '4.6.1' >= '5.6'
  => false

我在网上的几个地方看到人们使用 Gem::Version.new() 来比较语义版本。不过,这不是我的问题。任何人都可以向我解释 Ruby 似乎如何能够在没有任何库的帮助下比较语义版本字符串吗?当我用数字比较运算符比较两个字符串时会发生什么?

从上面的测试我想我可以确认它不是简单地比较每个字符串的第一个/最后一个字符的ascii值。它也没有使用字符串长度作为主要比较,这是我所期望的。

它检查字符串中每个单独字符的序数。它会在同一索引第一次出现不匹配时停止。序数越高,字符是 "bigger"。基本上,它类似于:

first_string.chars.map(&:ord) >= second_string.chars.map(&:ord)

正如评论中所指出的,这不会导致自然排序,因此人们使用 Gem::Version:

'11' > '9' # => false

它正在比较纯字符串。

对于其中一个字符串的所有字符都位于第二个字符串的开头的字符串...但是如果第二个字符串的长度较长,则认为较短的字符串小于。

否则逐个比较字符,直到第一个字符串的 "x" 位置的字符不等于第二个字符串的 "x" 位置的字符,在这种情况下,前面的字符在字母数字序列中被认为小于。

'cat' < 'caterpillar' 
=> true

'cow' < 'caterpillar' 
=> false

如果版本号超过一位数,您不能依赖它来正确比较语义版本...所以

'5.10' >= '5.9'
=> false

(这不是人们所希望的)