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

How does Ruby compare semantic version strings?

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

1
2
3
4
5
6
7
8
9
10
11
12
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值。它也没有使用字符串长度作为我期望的主要比较。


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

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

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

1
'11' > '9' # => false

它正在比较纯字符串。

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

否则,将一个一个地比较字符,直到一个字符串的" x"位置的字符与第二个字符串的" x"位置的字符不相等,在这种情况下,应考虑字母数字顺序中的较早字符小于

1
2
3
4
5
'cat' < 'caterpillar'
=> true

'cow' < 'caterpillar'
=> false

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

1
2
'5.10' >= '5.9'
=> false

(这不是人们希望的)