我有一组关键词。任何关键字都可以包含空格符号 ['one', 'one two']
。我从这些关键词生成一个正则表达式,如 /\b(?i:one|one\two|three)\b/
。完整示例如下:
keywords = ['one', 'one two', 'three']
re = /\b(?i:#{ Regexp.union(keywords).source })\b/
text = 'Some word one and one two other word'
text.downcase.scan(re)
这段代码的结果是
=> ["one", "one"]
如何找到第二个关键字 one two
的匹配项并得到这样的结果?
=> ["one", "one two"]
最佳答案
正则表达式渴望匹配。一旦找到匹配项,他们就不会尝试找到另一个可能更长的匹配项(有一个重要的异常(exception))。
/\b(?i:one|one\two|three)\b/
永远不会匹配 one two
因为它总是匹配 一个
第一。你需要 /\b(?i:one two|one|three)\b/
所以它首先尝试 one two
。可能最简单的自动化方法是首先按最长的关键字排序。
keywords = ['one', 'one two', 'three']
re = Regexp.union(keywords.sort { |a,b| b.length <=> a.length }).source
re = /\b#{re}\b/i;
text = 'Some word one and one two other word'
puts text.scan(re)
请注意,我将整个正则表达式设置为不区分大小写,比 (?:...)
更易于阅读,并且将字符串小写是多余的。
异常(exception)是repetition像 +
、*
和 friend 。默认情况下,它们是贪婪的。 .+
将匹配尽可能多的字符。那是贪婪的。你可以让它变得懒惰,用 ?
来匹配它看到的第一件事。 .+?
将匹配单个字符。
"A foot of fools".match(/(.*foo)/); # matches "A foot of foo"
"A foot of fools".match(/(.*?foo)/); # matches "A foo"
关于ruby - 正则表达式只返回一个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41943461/