捕获不包括变量短语的短语

时间:2016-02-15 17:08:39

标签: ruby regex

我有一个正则表达式来捕获短语,这两个短语是两个单词的互斥组(字符串中的每个单词最多只能捕获一次)。我试图从捕获的组中排除特定(变量)短语。 @Casimir提供的正则表达式/\w+\s+\w+/将根据需要对字符串进行分区,匹配组,但我们还需要排除可能出现在字符串中任何位置的组,并且可能会多次出现。

对于字符串

'next saturday, swing dancing at the kato ballroom! bring friends!'

和短语'swing dancing'正则表达式应该返回下面返回的每个组,除了“跳舞”#39;。

测试用例:

"next saturday, swing dancing at the kato ballroom! bring friends!".
  scan(/((?!swing dancing)(?:\w+)\s(?!swing dancing)(?:\w+))/)
=> [["next saturday"], ["wing dancing"], ["at the"], ["kato ballroom"], ["bring friends"]]

链接http://rubular.com/r/Eogo29Ociz

"next saturday, swing dancing at the kato ballroom! come dancing with friends!"
  .scan(/((?!dancing)(?:\w+)\s(?!dancing)(?:\w+))/)
=> [["next saturday"], ["ancing at"], ["the kato"], ["ancing with"]]

链接http://rubular.com/r/1TpcveiuX0

那应该返回

[["next saturday"], ["at the"], ["kato ballroom"], ["with friends"]] 

正则表达式可能不需要重复否定前瞻,只要我们匹配短语任一侧的短语以排除。

我希望正则表达式对负前瞻和匹配结果完全不区分大小写。我尝试了/i选项,但我也可以像上面代码中那样预先对字符串进行修改。

为什么正则表达式不起作用,你有改进建议吗?

1 个答案:

答案 0 :(得分:3)

使用捕获组隔离目标并将之前不需要的字符串放入可选的非捕获组中:/\b(?:swing\s+dancing\W+)?(\w+\s+\w+)/

> "next saturday, swing dancing at the kato ballroom! bring friends!".scan(/\b(?:swing\s+dancing\W+)?(\w+\s+\w+)/)
=> [["next saturday"], ["at the"], ["kato ballroom"], ["bring friends"]] 

demo rubular

或使用\K功能:/\b(?:swing\s+dancing\W+)?\K\w+\s+\w+/

> "next saturday, swing dancing at the kato ballroom! bring friends!".scan(/\b(?:swing\s+dancing\W+)?\K\w+\s+\w+/)
=> ["next saturday", "at the", "kato ballroom", "bring friends"] 

两种方式相似。他们不试图避免“摇摆舞”,相反他们试图先找到它。然后,最后一项任务是将其从结果中排除。

第一个模式使用捕获组(因为扫描方法只返回捕获组,如果有的话),第二个模式使用\K来说明“在此之前不返回任何内容”