By default Ruby opens $stdin and $stdout in buffered mode. This means you can’t use Ruby to perform a grep-like operation filtering text. Is there any way to force Ruby to use line-oriented mode? I’ve seen various solutions including popen3 (which does buffered-mode only) and pty (which doesn’t separately handle $stdout and $stderr, which I require).
How do I do this? Python seems to have the same lack.
It looks like your best bet is to use STDOUT.syswrite and STDOUT.sysread – the following seemed to have reasonably good performance, despite being ugly code:
Note: Not sure you need #sync with #sysread, but if so you should probably sync STDOUT too. Also, it reads 8 bytes at a time into mybuff – you should experiment with this value, it’s highly inefficient / CPU heavy. Lastly, this code is hacky and needs a refactor, but it works – tested it using
ls -l ~/* | ruby rgrep.rb doc(where ‘doc’ is the search term)Second note: Apparently, I was so busy trying to get it to perform well, I failed to get it to perform correctly! As Dmitry Shevkoplyas has noted, if there is text in @overflow when EOFError is raised, that text will be lost. I believe if you replace the catch with the following, it should fix the problem:
(if you found that helpful, please upvote Dmitry’s answer!)