0

如果已经在 Ruby 设置中问过这个问题,我深表歉意——我在发布之前检查过,但老实说,这已经是很长的一天了,如果我遗漏了显而易见的事情,我提前道歉!

我有以下字符串,其中包含系统上安装的软件包列表,由于某种原因,我最难解析它。我知道在 Ruby 中必须有一种直截了当的方法来做到这一点,但我一直在做这件事。

我想将下面的多行、制表符分隔的字符串解析为一个数组数组,然后我可以使用 each_with_index 循环遍历每个数组元素,并将 HTML 代码吐出到我的 Rails 应用程序中。

str = 'Product and/or Software Full Name 5242     [version 6.5.24]     [Installed on: 12/31/2015]

 Product and/or Software Full Name 5426     [version 22.4]     [Installed on: 06/11/2013]

 Product and/or Software Full Name 2451     [version 1.63]     [Installed on: 12/17/2015]

 Product and/or Software Full Name 5225     [version 43.22.51]     [Installed on: 11/15/2011]

 Product and/or Software Full Name 2420     [version 43.51-r2]     [Installed on: 12/31/2015]'

最终结果将是一个包含 5 个元素的数组,如下所示:

[[“产品和/或软件全名 5245”],[“版本 6.5.24”],[“安装日期:2015 年 12 月 31 日”],[“产品和/或软件全名 5426”],[ "版本 22.4"],["安装日期: 06/11/2013"],["产品和/或软件全名 2451"],["版本 1.63"],["安装日期: 12/17/2015" ]]

请注意:为简洁起见,仅显示了 5 个数组中的 3 个

我宁愿从“版本”和“安装在”中去掉括号,但如果不能轻易地将其纳入答案,我可以单独使用 gsub 来做到这一点。

最后一件事是,多行字符串中的每一行并不总是有一个“安装在”条目,因此答案需要在适用时考虑到这一点。

4

1 回答 1

1

这应该这样做:

expr = /(.+?)\s+\[([^\]]+)\](?:\s+\[([^\]]+)\])?/
str.scan(expr)

这个表达式实际上并没有看起来那么复杂。它看起来很复杂,因为我们要匹配必须转义的方括号,并且还要使用正则表达式语言中的方括号括起来的字符类。总之,它增加了很多噪音。

这里是分开的:

expr = /
  (.+?)  # Capture #1: Any characters (non-greedy)

  \s+    # Whitespace
  \[     # Literal '['
    (      # Capture #2:
      [^\]]+   # One or more characters that aren't ']'
    )
  \]     # Literal ']'

  (?:    # Non-capturing group
    \s+    # Whitespace
    \[     # Literal '['
      ([^\]]+) # Capture #3 (same as #2)
    \]     # Literal ']'
  )?     # Preceding group is optional
/x

如您所见,第三部分与第二部分相同,只是它位于非捕获组中,后跟 a?使其可选。

值得注意的是,如果产品名称包含方括号,这可能会失败。如果这是可能的,一个潜在的解决方案是在匹配中包含versionandInstalled文本,例如:

expr = /(.+?)\s+\[(version [^\]]+)\](?:\s+\[(Installed [^\]]+)\])?/

PS这是一个使用的解决方案String#split

expr = /\]?\s+\[|\]$/
res = str.each_line.map {|ln| ln.strip.split(expr) }
        .reject {|arr| arr.empty? }

如果您的产品名称中有方括号,则可能的解决方法是指定部件之间的最小空格数,例如:

expr = /\]?\s{3,}\[|\]$/

...这当然取决于产品名称的连续空格不超过三个。

于 2016-03-01T19:08:54.540 回答