Ich verwende Ubuntu Linux. Angenommen, es gibt ein Programm namens myprogram
. Dieses Programm fordert den Benutzer zur Eingabe auf; genauer gesagt muss der Benutzer bei entsprechender Aufforderung eine Ganzzahl eingeben und drücken Enter. Ich möchte diesen Prozess mithilfe eines Bash-Skripts automatisieren. Insbesondere möchte ich myprogram
beispielsweise 100 Mal ausführen (mit einem Zähler, der von bis i
geht ). Bei jeder Ausführung von möchte ich bei entsprechender Aufforderung den aktuellen Wert von eingeben . 1
100
myprogram
i
(Übrigens myprogram
werden Optionen/Schalter akzeptiert -options
, die alle konstant sind und somit im Bash-Skript angegeben werden.)
Ein unvollständiges Gerüst dieses Bash-Skripts könnte wie folgt aussehen:
#!/bin/bash
for i in {1..100}
do
myprogram -options
done
Nun möchte ich den obigen Code so ändern, dass i
auf Nachfrage des Programms der aktuelle Wert von eingetragen wird. Wie kann ich das am besten bewerkstelligen?
Die Website der von mir verwendeten Software schlägt vorusing <<EOF
am Ende der myprogram -options
Zeile. Ich denke, das sagt bash, dass es am „Ende der Datei“ nach der zu verwendenden Eingabe suchen soll. Aber was, wenn ich die Eingabe nicht am Ende der Zeile platzieren möchte?Ende<<
der Datei? Was ist, wenn ich es direkt nach dem oder einfügen möchte <
?
Der Grund dafür ist, dass die Dinge komplizierter werden. Ich könnte beispielsweise einen ganzzahligen Zähler einführen j
, der sich nicht linear und nicht sequentiell ändert. Ich würde dann bei jeder Iteration den aktuellen Wert von eingeben wollen j
, myprogram
aber der Wert von j
kann sich zwischen dem Aufruf von myprogram -options
und dem Ende der Datei ändern EOF
.
Haben Sie Vorschläge?
Antwort1
Bei fast allen Programmen sollten sowohl echo $i | myprogram -options
als auch myprogram -options <<<$i
funktionieren, indem das Programm $i
über die Standardeingabe gespeist wird.
<foo
verwendet den Inhalt der Datei foo
mit dem Namen stdin.
<<foo
foo
wird den Text zwischen diesem und einer Zeile, die ausschließlich aus besteht , als Standardeingabe verwenden . Dies ist einehier Dokument(Heredoc) EOF
bedeutet, wie Gilles sagte, nicht wirklich das Ende der Datei, sondern ist nur ein allgemeiner Heredoc-Abgrenzungsparameter (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 Standardeingabe, wie ich oben gezeigt habe. Dies nennt manhierstring, da es im Gegensatz zu einem ganzen Block, wie in einem Heredoc, einen kurzen String verwendet. Herestrings funktionieren in Bash, aber nicht in /bin/sh
.
Antwort2
Die von dieser Website empfohlene Syntax heißthier Dokument. Die Eingabe in die Datei program beginnt unmittelbar unter der Zeile, die enthält <<EOF
, und wird nicht durch das Ende des Skripts beendet, sondern durch eine Zeile, die genau den Text enthält EOF
(achten Sie darauf, dass keine zusätzlichen Leerzeichen vorhanden sind). Übrigens können Sie jeden Endmarker verwenden, der kein Shell-Sonderzeichen enthält: EOF
ist kein Schlüsselwort, sondern lediglich Tradition.
#!/bin/bash
for i in {1..100}
do
myprogram -options <<EOF
$i
EOF
for j in {1..42}; do
myprogram2 <<EOF
$i
$j
EOF
done
done
Antwort3
Hier sind die Dokumente, wie sie oben von Kevin und Gilles erwähnt wurden, oder in vielen Fällen funktioniert auch eine einfache Weiterleitung.
Für kompliziertere Situationen sollten Sie sich Expect oder ähnliches ansehen (z. B. ist das CPAN-Modul Expect::Simple 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, einsehrprimitive Implementierung der Idee in sh oder bash mit while und read.
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 ihm dann die gewünschte Eingabe zuzuführen.
Ein häufiges Anwendungsbeispiel ist die Automatisierung der Anmeldung, indem die Zeichenfolge „ogin:“ „erwartet“ (d. h. darauf gewartet wird), der Anmeldename gesendet wird, dann die Zeichenfolge „word:“ erwartet wird und das Kennwort gesendet wird.
Eine letzte Möglichkeit, wenn Sie den Quellcode von myprogram haben, besteht darin, ihn einfach so zu ändern, dass er die gewünschte Eingabe als Befehlszeilenoption akzeptiert. Das ist zwar anfangs vielleicht etwas mehr Arbeit, aber viel weniger ärgerlich, als mit Expect herumzuspielen oder Daten in ein Programm einzuspeisen, das nicht für diese Verwendung konzipiert wurde.
... und vergessen Sie nicht, Ihren Patch an myprogram zurück an den Upstream zu senden :) Selbst wenn ihnen nicht gefällt, wie Sie es codiert haben, gefällt ihnen die Idee vielleicht so gut, dass sie die Funktion selbst hinzufügen. Upstream-Entwickler schätzen in der Regel Leute, die sich ins Zeug legen und etwas beitragen, anstatt Forderungen zu stellen oder sich zu beschweren.