Ich verwende Ubuntu Linux. Angenommen, es gibt ein Programm namens myprogram
. Dieses Programm fordert den Benutzer zur Eingabe auf. Insbesondere muss der Benutzer bei Aufforderung eine Ganzzahl eingeben und drücken Enter. Ich möchte diesen Prozess mithilfe eines Bash-Skripts automatisieren. Insbesondere möchte myprogram
ich beispielsweise 100 Mal ausführen (unter Verwendung eines Zählers, i
der von 1
bis geht 100
). Bei jeder Ausführung von myprogram
möchte ich den aktuellen Wert von eingeben, i
wenn ich dazu aufgefordert werde.
(Übrigens, myprogram
nimmt Optionen / Schalter -options
, die alle konstant sind und somit im Bash-Skript angegeben werden.)
Ein unvollständiges Grundgerüst dieses Bash-Skripts könnte sein:
#!/bin/bash
for i in {1..100}
do
myprogram -options
done
Jetzt möchte ich den obigen Code so ändern, dass der aktuelle Wert von i
eingegeben wird, wenn das Programm Sie dazu auffordert. Was ist der beste Weg, dies zu tun?
Die Website der von mir verwendeten Software schlägt die Verwendung <<EOF
am Ende der myprogram -options
Zeile vor. Ich denke, dass dies bash anweist, sich das "Ende der Datei" für die zu verwendende Eingabe anzusehen. Aber was ist, wenn ich die Eingabe nicht am Ende der Datei platzieren möchte ? Was ist, wenn ich es sofort nach dem <<
oder setzen möchte <
?
Der Grund ist, dass die Dinge komplizierter werden. Zum Beispiel kann ich einen ganzzahligen Zähler einführen j
, der sich auf nichtlineare, nicht sequentielle Weise ändert. Ich möchte dann bei jeder Iteration den aktuellen Wert von j
to myprogram
eingeben, aber der Wert von j
kann sich zwischen dem Aufruf von myprogram -options
und dem Ende der Datei ändern EOF
.
Hast du irgendwelche Vorschläge?
Antworten:
Für fast alle Programme funktionieren beide
echo $i | myprogram -options
undmyprogram -options <<<$i
sollten funktionieren, indem das Programm$i
über die Standardeingabe eingespeist wird.<foo
verwendet den Inhalt der Datei mit dem Namenfoo
stdin.<<foo
verwendet den Text zwischen diesem und einer Zeile, die ausschließlichfoo
als Standardeingabe besteht. Dies ist ein Dokument hier (Heredoc), wie Gilles sagte;EOF
bedeutet eigentlich nicht das Ende der Datei, es ist nur ein üblicher Heredoc-Abgrenzer (in diesem Beispiel verwenden wir stattdessen "foo").<<<foo
verwendet die Zeichenfolge "foo" als Standardeingabe. Sie können auch eine Variable angeben$foo
, und die Shell verwendet ihren Inhalt als stdin, wie oben gezeigt. Dies wird als Herestring bezeichnet , da im Gegensatz zu einem ganzen Block wie bei einem Heredoc eine kurze Zeichenfolge verwendet wird. Herestrings arbeiten in Bash, aber nicht in/bin/sh
.quelle
Die von dieser Website empfohlene Syntax wird hier als Dokument bezeichnet . Die Eingabe in das Dateiprogramm beginnt unmittelbar unter der Zeile, die enthält
<<EOF
, und wird nicht am Ende des Skripts beendet, sondern durch eine Zeile, die genau den Text enthältEOF
(achten Sie darauf, dass keine zusätzlichen Leerzeichen vorhanden sind). Übrigens können Sie jeden Endmarker verwenden, der kein Shell-Sonderzeichen enthält: EsEOF
ist kein Schlüsselwort, es ist lediglich traditionell.quelle
END_OF_WHATEVER_FUNCTION
. Manchmal ist der Versuch, Platz / Größe zu "sparen", eine Verschwendung von Aufwand, da dadurch Unklarheiten darüber entstehen, was tatsächlich passiert.sleep
zwischen den Befehlen aus dem Skript lesen?Hier funktionieren Dokumente, wie sie sowohl von Kevin als auch von Gilles oben erwähnt wurden, oder einfache Rohrleitungen funktionieren in vielen Fällen.
In komplizierteren Situationen sollten Sie sich Expect oder ähnliches ansehen (z. B. das CPAN-Modul Expect :: Simple ist eine sehr einfach zu verwendende Perl-Implementierung). Ich persönlich bevorzuge das Perl-Modul (Expect selbst ist tcl), aber es gibt Implementierungen für viele gängige Skriptsprachen. Es ist sogar möglich, eine sehr primitive Implementierung der Idee in sh oder bash mit while und read zu schreiben .
Die allgemeine Idee von Expect und ähnlichen Tools besteht darin, auf eine bestimmte Zeichenfolge oder ein bestimmtes Muster in der Ausgabe eines Programms zu warten und diese dann mit der gewünschten Eingabe zu versehen.
Ein häufiges Beispiel ist die Automatisierung der Anmeldung, indem Sie die Zeichenfolge "ogin:" "erwarten" (dh darauf warten), den Anmeldenamen senden, dann die Zeichenfolge "word:" erwarten und das Kennwort senden.
Eine letzte Option, wenn Sie die Quelle von myprogram haben, besteht darin, es einfach so zu ändern, dass die Eingabe, die Sie ihm geben möchten, als Befehlszeilenoption verwendet wird. Dies mag im Vorfeld etwas aufwändiger sein, ist jedoch weitaus weniger erschwerend als das Herumspielen mit Expect oder das Weiterleiten von Daten an ein Programm, das nicht für die Verwendung auf diese Weise entwickelt wurde.
... und vergessen Sie nicht, Ihren Patch wieder stromaufwärts an myprogram zu senden :) Auch wenn ihnen die Art und Weise, wie Sie ihn codiert haben, nicht gefällt, gefällt ihnen die Idee möglicherweise genug, um die Funktion selbst hinzuzufügen. Upstream-Entwickler neigen dazu, Leute zu schätzen, die sich von ihrem Hintern lösen und eher dazu beitragen, als zu fordern oder sich zu beschweren.
quelle