解析复杂的版本字符串

时间:2011-02-12 11:58:58

标签: regex

我有一个以下方案的字符串:

  

VersionNumber.VersionString-VersionNumber.VersionString

这样可以将以下示例字符串转换为信息数组:

1. 1.x-2.x             => (1, 'x', '2', 'x')
2. 1.2-3.4             => (1, 2, 3, 4)
3. 1.2-3.4-beta5       => (1, 2, 3, '4-beta5')
4. 1.2-beta3-3.4       => (1, '2-beta3', 3, 4)
5. 1.2-beta3-4.5-beta6 => (1, '2-beta3', 4, '5-beta6')

解析的逻辑是:

  1. 第一个元素是第一个时期之前的所有内容。
  2. 第二个元素是紧靠数字之前的连字符。
  3. 第三个元素总是以数字开头,一直到下一个时期。
  4. 第四个元素就是这个时期之后的一切。
  5. 注意:

    • 第二个元素是一个任意字符串,但永远不会有一个紧跟在数字前面的连字符(例如2-3无效,但2-beta4是)。
    • 第三个元素始终以数字开头,并在连字符后面开始。

    我已经能够使用以下表达式解析前三个案例:

    (.+?).(.+?)-(.+?).(.*)
    

    但是我不知道如何修改它以处理案例4和5(当第二个元素包含连字符时)。我想到的两种方法是:

    1. 修改第二个组以匹配紧靠数字之前的连字符之前的所有内容。
    2. 修改第二个组以匹配所有内容,直到它仅在第一个连字符位于非数字字符之前才会到达第二个连字符。
    3. 据推测,第一种方法是正确/最简单的方法,但我正在努力想出正确的正则表达式来表达它。

2 个答案:

答案 0 :(得分:3)

试试这个:

(.+?)\.(.*)-(.+?)\.(.*)

实际上,即使这样也可行:

(.*)\.(.*)-(.*)\.(.*)

你的问题是你没有逃避这段时间,所以它把它视为匹配任何一个字符而不是匹配一段时间。

<强>更新

因此,如果VersionString可以包含句点/连字符,请遵循您的解析逻辑,这应该有效:

(\d*)\.(.*)-(\d*)\.(.*)

它说,

  1. 匹配所有数字(与您的第一个VersionNumber匹配)
  2. 匹配数字之前的第一个句点和最后一个连字符之间的所有内容(感谢贪婪的匹配)
  3. 匹配连字符后但在句点之前的所有数字
  4. 匹配其余
  5. 字符串:

    1.2-b.e.t.a.3-4.5-b.e.t.a.6 => '1'  '2-b.e.t.a.3'   '4' '5-b.e.t.a.6'
    

    如果你对versionstring中的连字符发疯了也会有效:

    1.2-b-e.t-a.3-4.5-b-e.t-a.6 => '1'  '2-b-e.t-a.3'   '4' '5-b-e.t-a.6'
    

答案 1 :(得分:2)

VersionString可以包含点吗?如果没有,这应该有效:

(\d+)\.([^.]+)-(\d+)\.(\S+)

[^.]+最初匹配到下一个点的所有内容,但后来稍微回溯。如果VersionString 可以包含一个点,您可以使用:

(\d+)\.(\S+?)-(\d+)\.(\S+)

VersionNumber部分中明确匹配的数字用于强制执行“以连字符开头的数字”规则。

(实际上,(.+?)的效果也一样;我使用(\S+?)因为我正在测试正则表达式从邮件的全文中删除版本字符串。)

编辑:根据以下评论,这是最终版本:

(\d+[^.]*)\.(\S+?)-(\d+[^.]*)\.(\S+)