使用正则表达式检测版本号的特定格式

时间:2016-08-24 00:21:47

标签: ruby regex

我希望提取包含版本号的数组元素,其中版本号位于字符串的开头或结尾,或者用空格填充,并且是一系列数字和句点,但不会启动或结束一段时间。例如“10.10 Thingy”和“Thingy 10.10.5”是有效的,但“Whatever 4”不是。

haystack = ["10.10 Thingy", "Thingy 10.10.5", "Whatever 4", "Whatever 4.x"]
haystack.select{ |i| i[/(?<=^| )(\d+)(\.\d+)*(?=$| )/] }
=> ["10.10 Thingy", "Thingy 10.10.5", "Whatever 4"]

我不确定如何修改正则表达式以至少需要一个句点,以便结果中不包含“Whatever 4”。

2 个答案:

答案 0 :(得分:2)

这只是Archonic的答案的一个小变种。

r = /
    (?<=\A|\s) # match the beginning of the string or a space in a positive lookbehind
    (?:\d+\.)+ # match >= 1 digits followed by a period in a non-capture group, >= 1 times 
    \d+        # match >= 1 digits
    (?=\s|\z)  # match a space or the end of the string in a positive lookahead
    /x         # free-spacing regex definition mode

haystack = ["10.10 Thingy", "Thingy 10.10.5", "Whatever 4", "Whatever 4.x"]

haystack.select { |str| str =~ r }
  #=> ["10.10 Thingy", "Thingy 10.10.5"]

问题不是返回版本信息,而是返回具有正确版本信息的字符串。因此,不需要外观:

r = /
    [\A\s\]    # match the beginning of the string or a space
    (?:\d+\.)+ # match >= 1 digits followed by a period in a non-capture group, >= 1 times 
    \d+        # match >= 1 digits
    [\s\z]     # match a space or the end of the string in a positive lookahead
    /x         # free-spacing regex definition mode

haystack.select { |str| str =~ r }
  #=> ["10.10 Thingy", "Thingy 10.10.5"]

假设有人想要获得包含有效版本的字符串和这些字符串中包含的版本。人们可以写下以下内容:

r = /
    (?<=\A|\s\) # match the beginning of string or a space in a pos lookbehind
    (?:\d+\.)+  # match >= 1 digits then a period in non-capture group, >= 1 times 
    \d+         # match >= 1 digits
    (?=\s|\z)   # match a space or end of string in a pos lookahead
    /x          # free-spacing regex definition mode

haystack.each_with_object({}) do |str,h|
  version = str[r]
  h[str] = version if version
end
  # => {"10.10 Thingy"=>"10.10", "Thingy 10.10.5"=>"10.10.5"}

答案 1 :(得分:1)

啊,哈哈!我知道我很亲密。

haystack.select{ |i| i[/(?<=^| )(\d+)(\.\d+)+(?=$| )/] }

(\.\d+)*末尾的星号允许该模式重复任意次数,包括零次。您可以使用(\.\d+){x,y}来限制它,其中x和y是最小和最大时间。您也只能识别(\.\d+){x,}的最小值。在我的情况下,我想要至少一次,这将是(\.\d+){1,},但这是(\.\d+)+的同义词。这只花了半天时间才算出来......