Match all occurrences of a regex
有没有一种快速的方法可以找到Ruby中正则表达式的每一个匹配项?我查看了ruby stl中的regex对象,并在Google上搜索到了无效的结果。
- 我读到这是我如何搜索一个字符串的所有正则表达式和可怕的困惑…
使用scan应该可以做到:
- 但这件案子又是怎么回事呢?"配我!".scan(/…/)=["mat","ch""me!"],但所有出现的/../将是["mat"、"atc"、"tch"、"ch"…]
- 不会的。/…/是一个普通的贪婪regexp。它不会在匹配的内容上回溯。您可以尝试使用一个懒惰的regexp,但即使这样也可能不够。请看一下regexp-doc ruby-doc.org/core-1.9.3/regexp.html,以正确表达regexp:)
- @MichaelDickens有一些方法可以让Perl Regex做到这一点,这样您也可以拉出所有重叠的匹配,但据我所知,只有Perl本身和PCRE支持这种匹配操作。
- 这看起来像一颗红宝石。为什么这是字符串而不是其他regexp东西的regexp?在regexp的文档中甚至没有提到
- 我想是因为它是在字符串上定义和调用的,而不是在正则表达式上…但这确实有道理。您可以编写一个正则表达式来使用regex match捕获所有匹配项,并对捕获的组进行迭代。这里编写一个部分匹配函数,并希望它在给定的字符串上应用多次,这不是regexp的责任。我建议您检查scan的实现,以便更好地理解:ruby doc.org/core-1.9.3/string.html method-i-scan
- @如果你想的话,你可以自己做一个关于regex的方法:class Regex
def scan(string)
string.scan(self)
end
end。
- @迈克尔迪肯:在这种情况下,你可以使用/(?=(...))/。
- 似乎scan不支持regex中的反向引用(与match不同)
- 是否有类似scan的东西返回索引而不是值?
- @贾斯汀,我不知道
- 感谢@xfix,加入一个平面阵列/(?=(...))/.flatten
- 谢谢@xfix,这对我来说非常有效,但是你能解释一下为什么使用积极的先行和捕获组会在这里起作用吗?谢谢!
- @德龙高使Regex引擎认为匹配结束位置是起始位置。通常,匹配不能重叠,为了避免这个问题,regex引擎从上一个匹配的结束位置开始搜索。
- 维克多?使用扫描而不删除分隔符怎么样?你提到过这个吗?结果=文本。扫描(/开始(.*?)α{{端}/m)
- 假设str ="a1ab2cd3d",我们希望找到前面和后面都是同一个字母的所有数字。我们可以使用regex r = /(?<=(\p{Alpha}))\d(?=\1)/。然后是str.scan(r) #=> [["a"], ["d"]],这不是想要的,而是可以理解的,因为scan对待捕获组的方式。但是,我们可以得到如下所需的结果:str.gsub(r).to_a #=> ["1","3"]。我的观点是,scan并不总是解决方案。
要查找所有匹配的字符串,请使用String类的scan方法。
1 2 3
| str ="A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54","3","1","7","3","36","0"] |
如果您希望MatchData是Regexp类的match方法返回的对象类型,请使用以下方法
1 2
| str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData"54">, #<MatchData"3">, #<MatchData"1">, #<MatchData"7">, #<MatchData"3">, #<MatchData"36">, #<MatchData"0">] |
拥有MatchData的好处是,您可以使用像offset这样的方法。
1 2 3 4 5
| match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8] |
如果你想了解更多,也可以参考这些问题。如何获取字符串中所有出现的Ruby正则表达式的匹配数据?与支持命名捕获的枚举器匹配的Ruby正则表达式如何找出Ruby中每个匹配的起点
阅读Ruby中的特殊变量$&、$'、$1、$2将非常有帮助。
如果有带组的regexp:
1 2
| str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/ |
使用字符串扫描方法查找匹配的组:
1 2
| str.scan re
#> [["54"], ["1"], ["3"]] |
要查找匹配的图案:
1 2
| str.to_enum(:scan,re).map {$&}
#> ["54m","1t","3r"] |