【问题标题】:Parsing a complex version string解析复杂的版本字符串
【发布时间】:2011-02-13 02:57:10
【问题描述】:

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

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. 第四个元素是句号之后的所有内容。

注意事项:

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

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

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

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

  1. 修改第二组以匹配紧接在数字前面的连字符之前的所有内容。
  2. 仅当第一个连字符紧接在非数字字符之前时,修改第二组以匹配所有内容,直到它碰到第二个连字符。

大概第一种方法是正确/最简单的方法,但我正在努力想出正确的正则表达式来表达它。

【问题讨论】:

  • 您的方案与解析步骤 3 的逻辑不匹配“第三个元素始终以数字开头,并且一直到下一个周期。”你的方案应该是“VersionNumber.VersionString-VersionNumber.VersionString”而不是“VersionNumber.VersionString-VersionNumber-VersionString”
  • 是的,但在你的问题中,你的方案是 Number.String-Number-String(错字?),最后一个连字符应该是我认为的句号,这让我有点困惑。
  • @Joe 哦,我明白了。你是对的,这是一个错字。抱歉,我以为你在暗示我的逻辑表明我想要“Number.String-Number-String”。

标签: regex


【解决方案1】:

试试这个:

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

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

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

您的问题是您没有转义句点,因此它将其视为匹配任何字符而不是匹配句点。

更新:

因此,如果 VersionString 可以包含句点/连字符,按照您的解析逻辑,这应该可以工作:

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

上面写着,

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

字符串:

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-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'

【讨论】:

  • 啊,太好了,这比我想出的解决方案还要简单。谢谢!
  • 我发现这个网站对于测试正则表达式的东西非常有用,不确定你是否已经知道了,fileformat.info/tool/regex.htm
【解决方案2】:

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

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

[^.]+ 最初将所有内容匹配到下一个点,但随后会回溯一点。如果VersionString 可以包含一个点,你可以使用这个:

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

VersionNumber 部分中明确匹配数字有助于强制执行您的“数字前有连字符”规则。

(实际上,(.+?) 也同样有效;我使用了(\S+?),因为我正在测试正则表达式,从您的消息全文中提取版本字符串。)

编辑:根据下面的 cmets,这是最终版本:

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

【讨论】:

  • VersionString 中的点没有限制:您的第二个表达式效果很好,稍作修改:(\d+\S*)\.(\S+?)-(\d+\S*)\.(\S+) VersionNumber 必须以数字开头,但在初始数字之后没有限制。跨度>
  • @Mark 如果 VersionString 中没有点限制,那么版本 1.2-beta.3-4.5-beta.6 可能是有效的,对吧?不幸的是,使用您的表达式,它分成 (1.2-beta, 3, 4.5-beta, 6) 而不是 (1, 2-beta.3, 4, 5-beta.6)
  • @Joe 是对的,但我们应该能够假设版本 Number 不能包含点,不是吗?试试(\d+[^.]*)\.(\S+?)-(\d+[^.]*)\.(\S+)
  • @Joe,Alan 是对的:我概述的逻辑排除了第一个和第三个元素有点(第一个和第三个元素在达到句点时结束)。 @Alan 似乎可以解决问题。谢谢!
猜你喜欢
  • 2016-06-20
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多