我在Ruby中构建一个程序,必须在其他程序中阅读' stdout
并向stdin
发送一些文字。我找到的当前解决方案是使用JRuby并使用一些熟悉的Java函数来完成任务。是否还有一个纯Ruby解决方案?
require 'java'
java_import java.lang.ProcessBuilder
java_import java.io.PrintStream
java_import java.util.Scanner
process = ProcessBuilder.new("bc", "-i").start
Thread.new {
input = Scanner.new(process.input_stream)
while input.has_next_line? do
puts("<- bc: " + input.next_line)
end
}
output = PrintStream.new(process.output_stream)
loop do
s = gets.chomp
if s == "exit"
break
end
output.println(s)
output.flush
end
程序运行
<- bc: bc 1.06.95
<- bc: Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
<- bc: This is free software with ABSOLUTELY NO WARRANTY.
<- bc: For details type `warranty'.
1+1
<- bc: 1+1
<- bc: 2
<- bc:
2*3
<- bc: 2*3
<- bc: 6
<- bc:
exit
答案 0 :(得分:0)
如果你想读取程序的输出,那么最好的办法就是产生一个伪终端(pty),这样它的输出就是行缓冲的。幸运的是,使用Ruby的PTY模块非常容易。在示例中,我使用IO.select
和非阻塞调用来避免线程。
#!/usr/bin/env ruby
require 'pty'
r, w, pid = PTY.spawn('bc -i')
running = true
while running
fds = IO.select([$stdin, r])
# fds[0] is an array of IO objects that are ready to be read from
fds[0].each do |fd|
if fd == r
output = r.read_nonblock(1024)
output.split("\n").each { |l| puts '<- bc: ' + l }
elsif fd == $stdin
line = $stdin.gets.strip
if line == 'exit'
running = false
break
end
w.write_nonblock(line + "\n")
end
end
end
Process.kill("TERM", pid)
Process.waitpid(pid)
输出,
<- bc: bc 1.06.95
<- bc: Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
<- bc: This is free software with ABSOLUTELY NO WARRANTY.
<- bc: For details type `warranty'.
<- bc:
1+1
<- bc: 1+1
<- bc: 2
2*3
<- bc: 2*3
<- bc: 6
exit