编辑:
我刚刚有了一个更好的主意,但我还是要去,包括旧的解决方案。
反向搜索的好处意味着您只需要读取文件的第一个块,直到指定的行号。对于接近,你越来越接近start_line,如果你发现一个匹配,你只是忘了旧的一个..你仍然在一些冗余数据的开始读入,但至少它是O(n)
path = "path/to/file"
start_line = 20
search_string = "findme!"
#assuming file is at least start_line lines long
match_index = nil
f = File.new(path)
start_line.times do |i|
line = f.readline
match_index = i if line.include? search_string
end
puts "Matched #{search_string} on line #{match_index}"
当然,请记住这个文件的大小在回答你的问题中起着重要的作用。
如果你想真的认真,你可以看看IO
类 - 看起来这可能是最终的解决方案。未经测试,只是一个想法。
f = File.new(path)
start_line.downto(0) do |i|
f.lineno = i
break if f.gets.include?(search_string)
end
原文:
对于一个详尽的解决方案,你可以尝试像下面这样。缺点是你需要将整个文件读入内存,但是如果它没有匹配到达顶部,它会考虑自下而上的情况。未经测试。
path = "path/to/file"
start_line = 20
search_string = "findme!"
#get lines of the file into an array (chomp optional)
lines = File.readlines(path).map(&:chomp)
#"cut" the deck, as with playing cards, so start_line is first in the array
lines = lines.slice!(start_line..lines.length) + lines
#searching backwards can just be searching a reversed array forwards
lines.reverse!
#search through the reversed-array, for the first occurence
reverse_occurence = nil
lines.each_with_index do |line,index|
if line.include?(search_string)
reverse_occurence = index
break
end
end
#reverse_occurence is now either "nil" for no match, or a reversed-index
#also un-cut the array when calculating the index
if reverse_occurence
occurence = lines.size - reverse_occurence - 1 + start_line
line = lines[reverse_occurence]
puts "Matched #{search_string} on line #{occurence}"
puts line
end
你有没有尝试过这个问题呢?如果是这样,任何代码或任何伪代码作为起点?否则,我们基本上为你做了很多。没有冒犯任何想法! – Kezzer 2010-07-06 13:08:41
通常'\ n'是一个新的行字符。您可以计数字符以指定该行。如果在文件中找到第二个'\ n',那么它后面的字符就是第3行的第一个字符。 – 2010-07-06 13:10:49
没有冒犯 - 我当然不希望你们为我做这项工作,就像我之前说过的 - 我这样做的成本可能超过了好处。 这实际上是一个较大努力的一小部分,我用一些不同的方法(从TSQL脚本到grep组合)对它进行了轻扫。 我非常喜欢Ruby,并为此接下来。我比任何事情都更好奇。我曾考虑将文件加载到数组中,然后向后迭代,但似乎缺乏在Ruby解决方案中经常遇到的优雅。 我的企图很难看 - 我希望有一位公主。 – 2010-07-06 13:35:45