我有一个类似xfooxbar
的字符串,想使用scan
将它拆分为['foo','bar']。(在有人问为什么不使用split
之前,真正的例子更复杂,在这个例子中,我还需要获取边界字符串,这个字符串被拆分后丢弃我问这个问题是为了更多地了解scan是如何工作的,或者是否有类似的选择,因为我发现这比我预期的要难。)
这不起作用,因为它一直扫描到字符串结尾:
"xfooxbar".scan(/(?:x)(.*)/)
> [["fooxbar"]]
问题是,当扫描发现下一个模式时,它不会神奇地停止扫描,并使它不贪婪地使用(.*?)只是让它空的,因为没有终点。所以我们可以添加一个端点作为下一个匹配:
"xfooxbar".scan(/(?:x)(.*)(?:x)/)
> [["foo"]]
问题是扫描显然与字符串中的所有可能模式都不匹配,因为它将指针保持在当前位置并且不会回溯所以它在第二个边界上匹配,并将从那里恢复扫描(the?:对此没有影响)。
最佳答案
使用如下的正向lookbehind断言。
irb(main):001:0> "xfooxbar".scan(/(?<=x)[^x]*/)
=> ["foo", "bar"]
(?<=x)
Positive lookbehind断言匹配前面必须有一个字母x
。[^x]*
匹配任何字符,但不匹配x
,零次或多次。