正则表达式返回奇怪的数组

时间:2012-05-25 18:03:48

标签: ruby regex

我想使用正则表达式从像这样的字符串中创建一个结果数组:

results|foofoofoo\nresults|barbarbarbar\nresults|googoogoo\ntimestamps||friday

这是我现在的正则表达式。它适用于Sublime Text的正则表达式搜索,但不适用于Ruby:

(results)\|.*?\\n(?=((results\|)|(timestamps\|\|)))

这将是理想的结果:

1. results|foofoofoo
2. results|barbarbar
3. results|googoogoo

相反,我得到了这些奇怪的回报,我无法理解。为什么这不选择结果行?

Match 1
1. results
2. results|
3. results|
4.  

Match 2
1. results
2. results|
3. results|
4.   

Match 3
1. results
2. timestamps||
3.  
4. timestamps||

以下是使用正则表达式的实际代码:

#create new lines for each regex'd line body with that body set as the raw attribute
host_scan.raw.scan(/(?:results)\|.*?\\n(?=((?:results\|)|(?:timestamps\|\|)))/).each do |body|
  @lines << Line.new({:raw => body})
end

4 个答案:

答案 0 :(得分:1)

作为Kendall Frey already stated,您创建了太多的捕获组。无需对第一个文字“结果|”进行分组,也无需将备用组的元素分组到单个非反向引用组中。你打算做的是这个正则表达式:

/results\|.*?(?=\\n(?:results\||timestamps\|\|))/

或者,如果您不介意重复\\n部分,则可以取消非捕获子组:

/results\|.*?(?=\\nresults\||\\ntimestamps\|\|)/

- 两者都会返回问题中指定的匹配值数组。

答案 1 :(得分:0)

我猜这与捕捉群组有关。如果您将所有(...)更改为(?:...),则会消除捕获组。

答案 2 :(得分:0)

使用split("\n"),而不是跳转到正则表达式,这是获取数据的一种更复杂的方法。

text = "results|foofoofoo\nresults|barbarbarbar\nresults|googoogoo\ntimestamps||friday"
ary = text.split("\n")

ary是:

[
  "results|foofoofoo",
  "results|barbarbarbar",
  "results|googoogoo",
  "timestamps||friday"
]

切片,你可以得到:

ary[0..2]
=> ["results|foofoofoo", "results|barbarbarbar", "results|googoogoo"]

编辑:

基于注释,字符串中有更多回车符和复杂字符:

require 'awesome_print'

text = "results|foofoofoo\nmorefoo\nandevenmorefoo\nresults|barbarbarbar\nandmorebar\nandyetagainmorebar\nresults|googoogoo\ntimestamps||friday"
ap text.sub(/\|\|friday$/, '').split('results')[1..-1].map{ |l| 'results' << l }

哪个输出:

[
  [0] "results|foofoofoo\nmorefoo\nandevenmorefoo\n",
  [1] "results|barbarbarbar\nandmorebar\nandyetagainmorebar\n",
  [2] "results|googoogoo\ntimestamps"
]

答案 3 :(得分:0)

答案结果是在括号中。用括号括起来会使它返回整个匹配而不仅仅是尾部分隔符。

host_scan.raw.scan(/((?:results\|.*?\\n)(?=(?:results\|)|(?:timestamps\|\|)))/).each do |body|
      @lines << Line.new({:raw => body})
end