我正在尝试拆分字符串:
"[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
进入以下数组:
[
["test","blah"]
["foo","bar bar bar"]
["test","abc","123","456 789"]
]
我尝试了以下内容,但这不太对:
"[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
.scan(/\[(.*?)\s*\|\s*(.*?)\]/)
# =>
# [
# ["test", "blah"]
# ["foo", "bar bar bar"]
# ["test", "abc |123 | 456 789"]
# ]
我需要在每个管道而不是第一个管道上拆分。实现这一目标的正确正则表达式是什么?
答案 0 :(得分:7)
s = "[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
arr = s.scan(/\[(.*?)\]/).map {|m| m[0].split(/ *\| */)}
答案 1 :(得分:6)
两种选择:
s = "[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
s.split(/\s*\n\s*/).map{ |p| p.scan(/[^|\[\]]+/).map(&:strip) }
#=> [["test", "blah"], ["foo", "bar bar bar"], ["test", "abc", "123", "456 789"]]
irb> s.split(/\s*\n\s*/).map do |line|
line.sub(/^\s*\[\s*/,'').sub(/\s*\]\s*$/,'').split(/\s*\|\s*/)
end
#=> [["test", "blah"], ["foo", "bar bar bar"], ["test", "abc", "123", "456 789"]]
它们都是从分割新行开始(扔掉周围的空格)。
第一个然后通过查找不是[
,|
或]
的任何内容来拆分每个块,然后抛弃额外的空格(调用strip
on每个)。
然后第二个抛弃前导[
并尾随]
(带空白),然后分割|
(带空格)。
使用单个scan
无法获得所需的最终结果。你能得到的最接近的是:
s.scan /\[(?:([^|\]]+)\|)*([^|\]]+)\]/
#=> [["test", " blah"], ["foo ", "bar bar bar"], ["123 ", " 456 789"]]
...丢弃信息,或者这个:
s.scan /\[((?:[^|\]]+\|)*[^|\]]+)\]/
#=> [["test| blah"], ["foo |bar bar bar"], ["test| abc |123 | 456 789"]]
...将每个“数组”的内容捕获为单个捕获,或者:
s.scan /\[(?:([^|\]]+)\|)?(?:([^|\]]+)\|)?(?:([^|\]]+)\|)?([^|\]]+)\]/
#=> [["test", nil, nil, " blah"], ["foo ", nil, nil, "bar bar bar"], ["test", " abc ", "123 ", " 456 789"]]
...最多硬编码为四个项目,并插入nil
所需的.compact
条目。
没有办法使用Ruby的scan
来获取像/(?:(aaa)b)+/
这样的正则表达式,并且每次重复匹配时都会获得多次捕获。
答案 2 :(得分:2)
为什么硬路径(单一正则表达式)?为什么不拆分的简单组合?以下是可视化过程的步骤。
str = "[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
arr = str.split("\n").map(&:strip) # => ["[test| blah]", "[foo |bar bar bar]", "[test| abc |123 | 456 789]"]
arr = arr.map{|s| s[1..-2] } # => ["test| blah", "foo |bar bar bar", "test| abc |123 | 456 789"]
arr = arr.map{|s| s.split('|').map(&:strip)} # => [["test", "blah"], ["foo", "bar bar bar"], ["test", "abc", "123", "456 789"]]
这可能远远低于scan
,但至少它很简单:)
答案 3 :(得分:2)
整个前提似乎有缺陷,因为它假设您总是会在子数组中找到替换,并且表达式将不包含字符类。不过,如果这是你真正想要解决的问题,那么这应该做到。
首先,str.scan( /\[.*?\]/ )
将为您提供三个数组元素,每个元素都包含伪数组。然后映射子数组,拆分交替字符。然后剥去子数组的每个元素的空格,并删除方括号。例如:
str = "[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
str.scan( /\[.*?\]/ ).map { |arr| arr.split('|').map { |m| m.strip.delete '[]' }}
#=> [["test", "blah"], ["foo", "bar bar bar"], ["test", "abc", "123", "456 789"]]
映射嵌套数组并不总是直观的,因此我将上面的列车残骸解开为更多程序代码以进行比较。结果是相同的,但以下可能更容易推理。
string = "[test| blah] \n [foo |bar bar bar]\n[test| abc |123 | 456 789]"
array_of_strings = string.scan( /\[.*?\]/ )
#=> ["[test| blah]", "[foo |bar bar bar]", "[test| abc |123 | 456 789]"]
sub_arrays = array_of_strings.map { |sub_array| sub_array.split('|') }
#=> [["[test", " blah]"],
# ["[foo ", "bar bar bar]"],
# ["[test", " abc ", "123 ", " 456 789]"]]
stripped_sub_arrays = sub_arrays.map { |sub_array| sub_array.map(&:strip) }
#=> [["[test", "blah]"],
# ["[foo", "bar bar bar]"],
# ["[test", "abc", "123", "456 789]"]]
sub_arrays_without_brackets =
stripped_sub_arrays.map { |sub_array| sub_array.map {|elem| elem.delete '[]'} }
#=> [["test", "blah"], ["foo", "bar bar bar"], ["test", "abc", "123", "456 789"]]