2013-06-12 2 views
5

Ich bin relativ neu in Ruby und kann anscheinend keine Möglichkeit finden, die Ausgabe eines externen Befehls zu erhalten. Ich muss die vom Befehl zurückgegebenen Werte extrahieren. Denn jetzt habe ich so etwas wie diese:Extrahiere Wert von stdout von Open3.popen3 durch RegEx und speichere es

stdin, stdout, stderr, wait_thr = Open3.popen3("#{path}/foobar", configfile) 

if /exit 0/ =~ wait_thr.value.to_s 
    runlog.puts("Foobar exited normally.\n") 
    puts "Test completed." 
    someoutputvalue = stdout.read("TX.*\s+(\d+)\s+") 
    puts "Output value: " + someoutputvalue 
end 

Aber ich bin mit eindeutig nicht der richtigen Methode auf stdout seit Rubin mir sagt, es String in Integer nicht konvertieren kann.

Was wäre der richtige Weg, dies zu tun? Ich kann nirgendwo in der Dokumentation die für stdout verfügbaren Methoden finden. Mit stout.read benutze ich Ruby 1.9.3.

aktualisieren

Um ganz klar zu sein, ich versuche, die Ausgabe des Programms zu lesen, einen regulären Ausdruck anwenden, und speichern Sie die extrahierten Wert in eine Variable für eine spätere Verwendung.

Also wenn die Ausgabe ist "TX So und so: 28" Ich möchte nur "28" bekommen (Ich validiert, dass die Regex oben entspricht, was ich übereinstimmen muss, frage ich mich nur, wie zu speichern dieser extrahierte Wert in einer Variablen).

+0

Wenn Sie nicht auf den Prozess kommunizieren wollen und nur seine Ausgabe lesen, 'capture3' wäre besser geeignet (und einfach). –

+0

Was ist das Argument zu lesen? Ich dachte, das einzige Argument, an dem du vorbeikamst, war, wie weit du in den Strom gehen solltest? Vielleicht versucht es, Ihr String-Argument als die ganze Zahl von Bytes zu behandeln? –

+0

@JoePym Das Argument ist eine XML-Datei, die von foobar zum Ausführen verwendet wird, wenn das Ihre Frage ist. – Astaar

Antwort

13

Alle erforderlichen Informationen sind in der Popen3 documentation, aber Sie müssen alles lesen und schauen Sie sich die Beispiele ziemlich sorgfältig. Sie können nützliche Informationen auch von der Process docs abrufen.

Vielleicht wird dies ‚splain es besser:

require 'open3' 

captured_stdout = '' 
captured_stderr = '' 
exit_status = Open3.popen3(ENV, 'date') {|stdin, stdout, stderr, wait_thr| 
    pid = wait_thr.pid # pid of the started process. 
    stdin.close 
    captured_stdout = stdout.read 
    captured_stderr = stderr.read 
    wait_thr.value # Process::Status object returned. 
} 

puts "STDOUT: " + captured_stdout 
puts "STDERR: " + captured_stderr 
puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed') 

Lauf dass Ausgänge:

STDOUT: Wed Jun 12 07:07:12 MST 2013 
STDERR: 
EXIT STATUS: succeeded 

Dinge zu beachten:

  • Sie haben oft zu close der stdin Strom. Wenn die aufgerufene Anwendung eine Eingabe in STDIN erwartet, bleibt sie hängen, bis der Stream geschlossen wird. Anschließend wird die Verarbeitung fortgesetzt.
  • stdin, stdout, stderr sind IO-Handles, so müssen Sie die IO class documentation lesen, um herauszufinden, welche Methoden verfügbar sind.
  • Sie müssen stdin zur Ausgabe puts, print oder write und read oder gets von stdout und stderr verwenden.
  • exit_status ist keine Zeichenfolge, sondern eine Instanz der Process :: Status-Klasse. Sie können versuchen, von seiner to_s Version zu analysieren, aber nicht. Verwenden Sie stattdessen die Accessoren, um zu sehen, was zurückgegeben wurde.
  • Ich ging in der ENV Hash, so dass das Kind-Programm Zugriff auf die gesamte Umgebung der Eltern sah. Das ist nicht nötig; Stattdessen können Sie eine reduzierte Umgebung für das Kind erstellen, wenn Sie nicht möchten, dass es auf alles zugreifen kann, oder Sie können die Ansicht der Umgebung verändern, indem Sie die Werte ändern.
  • Der Code stdout.read("TX.*\s+(\d+)\s+") in der Frage geschrieben ist, ähm ... Unsinn. Ich habe keine Ahnung, wo Sie das haben, da nichts in Rubys IO-Klasse für IO#read oder IO.read dokumentiert ist.

Es ist einfacher capture3 zu verwenden, wenn Sie zu STDIN des aufgerufenen Code nicht schreiben müssen:

require 'open3' 

stdout, stderr, exit_status = Open3.capture3('date') 

puts "STDOUT: " + stdout 
puts "STDERR: " + stderr 
puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed') 

Welche Ausgänge:

STDOUT: Wed Jun 12 07:23:23 MST 2013 
STDERR: 
EXIT STATUS: succeeded 

Wert von Extrahierung Eine Zeichenfolge, die einen regulären Ausdruck verwendet, ist trivial und wird von Regexp documentation gut abgedeckt. Ausgehend von der letzten Codebeispiel:

stdout[/^\w+ (\w+ \d+) .+ (\d+)$/] 
puts "Today is: " + [$1, $2].join(' ') 

Welche Ausgänge:

Today is: Jun 12 2013 

dass die String.[] Methode ist mit der extrem flexibel ist.

Eine alternative wird mit "genannt captures":

/^\w+ (?<mon_day>\w+ \d+) .+ (?<year>\d+)$/ =~ stdout 
puts "Today is: #{ mon_day } #{ year }" 

, die die gleiche Sache gibt. Der Nachteil der genannten Captures ist, dass sie langsamer sind, was ich als etwas unbedeutend empfinde.


"TX So and so: 28"[/\d+$/] 
=> "28" 
+0

Aber wenn ich nur 'puts stdout.read' drucke, warum ist die Verwendung einer Zwischenvariable notwendig (in meinem Fall ist die Regex im Block gemacht, so dass es kein Problem mit dem Bereich gibt)? Wie würde ich einen Wert mit einer Regex auf captained_stdout in Ihrem Beispiel extrahieren? – Astaar

+0

Ich habe es in einer Zwischenvariable gespeichert, um Ihnen zu zeigen, wie Sie von außerhalb des Blocks darauf zugreifen können. Wenn Sie das nicht tun müssen, tun Sie es nicht. Und Sie verwenden einen normalen regulären Ausdruck oder eine Teilzeichenkette, um einen Wert aus 'captured_stdout' zu extrahieren, es gibt nichts, das mysteriös oder magisch ist, es ist eine Zeichenkette, die alles enthält, was der aufgerufene Code zurückgibt. –

+0

Ich habe die Dokumentation genau gelesen, meine Frage ist allgemeiner bei Ruby und fragt im Grunde, wie man einen aus einem String extrahierten Wert über einen regulären Ausdruck speichert, der nicht in der Popen3-Dokumentation enthalten ist. Noch die Regexp-Dokumentation kann sagen. Das Beispiel, das Sie angegeben haben, funktioniert bereits für mich, da ich die Dokumentation gelesen habe. – Astaar

Verwandte Themen