查找重叠的正则表达式匹配

12
我想在一个给定的字符串中找到所有匹配项,包括重叠的匹配项。我该如何实现?
# Example
"a-b-c-d".???(/\w-\w/)  # => ["a-b", "b-c", "c-d"] expected

# Solution without overlapped results
"a-b-c-d".scan(/\w-\w/) # => ["a-b", "c-d"], but "b-c" is missing
2个回答

15

在正向先行断言中使用捕获:

"a-b-c-d".scan(/(?=(\w-\w))/).flatten
 # => ["a-b", "b-c", "c-d"]

请参见Ruby演示


完美运行,即使是复杂的模式也可以。"abaca".scan(/(?=(\w)(?:(?!\1)(\w))\1)/) #=> [["a", "b"], ["a", "c"]] - sschmeck
检查似乎不仅是不必要的,而且实际上对最终结果有害。 - Eli Sadoff
2
或者正向后查找:"a-b-c-d".scan(/(?<=(\w-\w))/).flatten - Cary Swoveland
3
伙计们,上面的代码片段中只使用 inspect 来在在线演示中打印演示结果,没有人告诉你在实际代码中使用 inspect。我将其删除以避免进一步的混淆。 - Wiktor Stribiżew

4

我建议采用非正则表达式的解决方案:

"a-b-c-d".delete('-').each_char.each_cons(2).map { |s| s.join('-') }
  #=> ["a-b", "b-c", "c-d"]

或者

"a-b-c-d".each_char.each_cons(3).select.with_index { |_,i| i.even? }.map(&:join)
  #=> ["a-b", "b-c", "c-d"]

或者

enum = "a-b-c-d".each_char
a = []
loop do
  a << "%s%s%s" % [enum.next, enum.next, enum.peek]
end
a #=> ["a-b", "b-c", "c-d"]

1
你的最后一种技巧非常非常棒。 - Sagar Pandya
1
很好的回答,但我明确地要求一个正则表达式。上面的模式只是我找到的最简单的一个来解释我的问题。我实际使用的模式是 (\w)(?:(?!\1)(\w))\1 - sschmeck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接