观即可。给定字符串,返回所有匹配(带有重叠)和这些匹配之前的文本。
示例即可。对于文本atatgcgcatatat
和查询atat
,有三个匹配项,所需的输出为atat
,atatgcgcatat
和atatgcgcatatat
。
问题即可。我使用Ruby 2.2和String#scan
方法来获得多个匹配项。我尝试使用lookahead,但正则表达式/(?=(.*?atat))/
返回以atat
结尾的每个子字符串。必须有一些正则表达式的魔法来解决这个问题,但我无法弄清楚正确的法术。
答案 0 :(得分:4)
我相信这至少比OP的回答更好:
text = "atatgcgcatatat"
query = "atat"
res = []
text.scan(/(?=#{query})/){res.push($` + query)} #`
res # => ["atat", "atatgcgcatat", "atatgcgcatatat"]
答案 1 :(得分:3)
鉴于正则表达式的性质和目的,没有办法做到这一点。当正则表达式匹配文本时,无法在另一个匹配项中包含相同的文本。因此,我能想到的最佳选择是使用后视来查找每场比赛的结束位置:
(?<=atat)
使用atatgcgcatatat
的示例输入,将返回以下三个匹配项:
然后,您可以遍历这些结果,获取每个结果的位置,然后获取从输入字符串的开头开始并在该位置结束的子字符串。如果您不知道如何获得每场比赛的位置,您可能会发现this question的答案很有帮助。
答案 2 :(得分:1)
你可以这样做:
str = 'atatgcgcatatat'
target = 'atat'
[].tap do |a|
str.gsub(/(?=#{target})/) { a << str[0, $~.end(0)+target.size] }
end
#=> ["atat", "atatgcgcatat", "atatgcgcatatat"]
请注意gsub
返回的字符串将被丢弃。
答案 3 :(得分:0)
看来,没有办法一次性解决问题。
一种可能的解决方案是使用Float#==
在使用String#scan
时获取匹配索引,然后返回切片字符串数组:
def find_by_end text, query
res = []
n = query.length
text.scan( /(?=(#{query}))/ ) do |m|
res << text.slice(0, $~.offset(0).first + n)
end
res
end
find_by_end "atatgcgcatatat", "atat" #=> ["atat", "atatgcgcatat", "atatgcgcatatat"]
@StevenDoggart提出了一个略有不同的解决方案。这是一个很好的短代码,使用this knowledge hack来解决问题:
"atatgcatatat".to_enum(:scan, /(?<=atat)/).map { $` } #`
#=> ["atat", "atatgcatat", "atatgcatatat"]
正如@CasimiretHippolyte所说,反转字符串可能有助于解决问题。它确实如此,但它不是最漂亮的解决方案:
"atatgcatatat".reverse.scan(/(?=(tata.*))/).flatten.map(&:reverse).reverse
#=> ["atat", "atatgcatat", "atatgcatatat"]