Ruby中#match返回正确结果但#scan仅匹配单个字母的原因探究
问题解答
核心原因
String#scan 和 String#match 的行为差异源于两者的设计逻辑:
match返回第一个匹配的完整MatchData对象,包含整个匹配字符串以及所有捕获组内容,所以你能看到整个重复序列"tttt"和捕获的单个字母"t"。scan在正则包含捕获组时,默认只收集捕获组的内容,而非整个匹配结果。你的正则(\p{alpha})\1{2,}有一个捕获组(用于捕获单个重复字母),因此scan返回的是每个匹配对应的捕获组值,也就是[["t"]]。
解决方法
如果想让scan返回整个重复的字符串序列,可以用以下两种方式:
1. 使用scan的块形式获取完整匹配
通过块参数结合全局变量$&(代表当前整个匹配结果)来收集内容:
matches = [] "gjhfgfcttttdfs".scan(/(\p{alpha})\1{2,}/) { matches << $& } # matches => ["tttt"]
2. 修改正则,添加外层捕获组
给整个匹配结构套一个外层捕获组,这样scan会同时返回整个匹配和内层捕获的单个字母:
"gjhfgfcttttdfs".scan(/((\p{alpha})\2{2,})/) # => [["tttt", "t"]]
注意:反向引用依赖捕获组,所以必须保留内层捕获组才能实现匹配重复字母的逻辑,无法直接替换为非捕获组。
内容的提问来源于stack exchange,提问作者Todd A. Jacobs
相关产品推荐
相关产品推荐

