Ruby - 将多行制表符分隔的字符串解析为数组数组
Ruby - Parse a multi-line tab-delimited string into an array of arrays
如果在 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 个元素的数组,如下所示:
[["Product and/or Software Full Name 5245"],["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"]]
请注意:为简洁起见,仅显示了 5 个阵列中的 3 个
我更愿意从 'version' 和 'Installed on' 中去掉括号,但如果不能轻易将其转化为答案,我可以单独使用 gsub 来做到这一点。
最后一件事是,多行字符串中的每一行不会总是有一个 'Installed on' 条目,因此答案需要在适用时考虑到这一点。
应该这样做:
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
如您所见,第三部分与第二部分相同,只是它位于非捕获组中,后跟 ?
使其成为可选。
值得注意的是,这可能会失败,例如产品名称包含方括号。如果可能的话,一个可能的解决方案是在匹配中包含 version
和 Installed
文本,例如:
expr = /(.+?)\s+\[(version [^\]]+)\](?:\s+\[(Installed [^\]]+)\])?/
P.S。这是一个使用 String#split
的解决方案:
expr = /\]?\s+\[|\]$/
res = str.each_line.map {|ln| ln.strip.split(expr) }
.reject {|arr| arr.empty? }
如果您的产品名称中有括号,这里可能的解决方法是指定各部分之间的最小空格数,例如:
expr = /\]?\s{3,}\[|\]$/
...这当然取决于产品名称的连续空格不超过三个。
如果在 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 个元素的数组,如下所示:
[["Product and/or Software Full Name 5245"],["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"]]
请注意:为简洁起见,仅显示了 5 个阵列中的 3 个
我更愿意从 'version' 和 'Installed on' 中去掉括号,但如果不能轻易将其转化为答案,我可以单独使用 gsub 来做到这一点。
最后一件事是,多行字符串中的每一行不会总是有一个 'Installed on' 条目,因此答案需要在适用时考虑到这一点。
应该这样做:
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
如您所见,第三部分与第二部分相同,只是它位于非捕获组中,后跟 ?
使其成为可选。
值得注意的是,这可能会失败,例如产品名称包含方括号。如果可能的话,一个可能的解决方案是在匹配中包含 version
和 Installed
文本,例如:
expr = /(.+?)\s+\[(version [^\]]+)\](?:\s+\[(Installed [^\]]+)\])?/
P.S。这是一个使用 String#split
的解决方案:
expr = /\]?\s+\[|\]$/
res = str.each_line.map {|ln| ln.strip.split(expr) }
.reject {|arr| arr.empty? }
如果您的产品名称中有括号,这里可能的解决方法是指定各部分之间的最小空格数,例如:
expr = /\]?\s{3,}\[|\]$/
...这当然取决于产品名称的连续空格不超过三个。