Похоже, что вам лучше всего использовать STDOUT.syswrite и STDOUT.sysread. Казалось, что следующее имеет довольно хорошую производительность, несмотря на то, что код выглядит ужасно:
STDIN.sync = true
STDOUT.syswrite "Looking for #{ARGV[0]}\n"
def next_line
mybuff = @overflow || ""
until mybuff[/\n/]
mybuff += STDIN.sysread(8)
end
overflow = mybuff.split("\n")
out, *others = overflow
@overflow = others.join("\n")
out
rescue EOFError => e
false # NB: There's a bug here, see below
end
line = next_line
while line
STDOUT.syswrite "#{line}\n" if line =~ /#{ARGV[0]}/i
line = next_line
end
Примечание: Не уверен, что вам нужен #sync с #sysread, но если это так, вам, вероятно, следует также синхронизировать STDOUT. Кроме того, он считывает 8 байтов за раз в mybuff - вы должны поэкспериментировать с этим значением, оно крайне неэффективно / сильно загружает процессор. Наконец, этот код является хакерским и нуждается в рефакторинге, но он работает - протестировал его, используя ls -l ~/* | ruby rgrep.rb doc
(где 'doc' - поисковый термин)
Второе замечание: по-видимому, я был так занят, пытаясь заставить его работать хорошо, я не смог заставить его работать правильно! Поскольку у Дмитрия Шевкопляса отмечено , если в @overflow есть текст, когда возникает EOFError, этот текст будет потерян. Я полагаю, что если вы замените защелку на следующую, это должно решить проблему:
rescue EOFError => e
return false unless @overflow && @overflow.length > 0
output = @overflow
@overflow = ""
output
end
(если вы сочли это полезным, пожалуйста, проголосуйте за Дмитрия ответ !)