两个选择:
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) }
irb> s.split(/\s*\n\s*/).map do |line|
line.sub(/^\s*\[\s*/,'').sub(/\s*\]\s*$/,'').split(/\s*\|\s*/)
end
两种方法都是首先通过换行符进行拆分(舍去周围的空格)。
第一种方法然后会在每个块中查找任何不属于[
、|
或]
的内容,并将额外的空格删除(对每个块调用strip
函数)。
第二种方法然后会删除前导的[
和尾随的]
(包括空格),然后按照|
进行拆分(包含空格)。
你无法只使用一个scan
函数得到最终想要的结果。最接近你可以得到的结果如下:
s.scan /\[(?:([^|\]]+)\|)*([^|\]]+)\]/
#=> [["test", " blah"], ["foo ", "bar bar bar"], ["123 ", " 456 789"]]
...会使信息丢失,或者是这个:
s.scan /\[((?:[^|\]]+\|)*[^|\]]+)\]/
…它将每个“数组”的内容作为单个捕获进行捕获,或者使用以下方法:
s.scan /\[(?:([^|\]]+)\|)?(?:([^|\]]+)\|)?(?:([^|\]]+)\|)?([^|\]]+)\]/
#=> [["test", nil, nil, " blah"], ["foo ", nil, nil, "bar bar bar"], ["test", " abc ", "123 ", " 456 789"]]
这段代码被硬编码为最多四个项,并插入了需要使用 .compact
去除的 nil
条目。
无法使用 Ruby 的 scan
方法,对于像 /(?:(aaa)b)+/
这样的正则表达式,每次匹配重复部分都会获得多个捕获。