Цель: Я пишу программу командной строки рабочего процесса в рубине, которая последовательно выполняет другие программы в оболочке UNIX, некоторые из которых требуют от пользователя ввода вход.Runy Open3.popen3 Ввод ввода в подпроцесс из командной строки
Проблема: Хотя я могу успешно справиться с stdout
и stderr
благодаря этой полезной blog post по Nick Charlton, я однако застрял на захват пользовательского ввода и передачи его в подпроцессов с помощью командной строки. Код следующим образом:
Метод
module CMD
def run(cmd, &block)
Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
Thread.new do # STDOUT
until (line = stdout.gets).nil? do
yield nil, line, nil, thread if block_given?
end
end
Thread.new do # STDERR
until (line = stderr.gets).nil? do
yield nil, nil, line, thread if block_given?
end
end
Thread.new do # STDIN
# ????? How to handle
end
thread.join
end
end
end
Вызов метода
Этот пример вызывает команду units
оболочки, который предлагает пользователю ввести единицу измерения, а затем запрашивает единица для конвертирования в. Вот как это будет выглядеть в оболочке
> units
586 units, 56 prefixes # stdout
You have: 1 litre # user input
You want: gallons # user input
* 0.26417205 # stdout
/3.7854118 # stdout
Когда я запускаю это из моей программы я ожидаю, чтобы иметь возможность взаимодействовать с ним точно таким же образом.
unix_cmd = 'units'
run unix_cmd do | stdin, stdout, stderr, thread|
puts "stdout #{stdout.strip}" if stdout
puts "stderr #{stderr.strip}" if stderr
# I'm unsure how I would allow the user to
# interact with STDIN here?
end
Примечания: Вызов run
метода этот способ позволяет пользователю быть в состоянии разобрать выходной, управление потоком процесса и добавлять пользовательский протоколирования.
Из того, что я собрал о STDIN, сниппета ниже, так как я понял, как обращаться с STDIN, есть явные пробелы в моих знаниях, потому что я все еще не уверен, как интегрировать этот в мой метод run
и передать вход в дочерний процесс.
# STDIN: Constant declared in ruby
# stdin: Parameter declared in Open3.popen3
Thread.new do
# Read each line from the console
STDIN.each_line do |line|
puts "STDIN: #{line}" # print captured input
stdin.write line # write input into stdin
stdin.sync # sync the input into the sub process
break if line == "\n"
end
end
Резюме: Я хочу понять, как обрабатывать ввод пользователя из командной строки с помощью метода Open3.popen3
так, что я могу позволить пользователям вводить данные в различные последовательности суб-команд, вызываемых из моей программы.
Я также люблю знать, как это сделать –