Automatisieren der Texteingabe aus einem Bash-Skript ohne Verwendung von EOF


10

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 myprogramich beispielsweise 100 Mal ausführen (unter Verwendung eines Zählers, ider von 1bis geht 100). Bei jeder Ausführung von myprogrammöchte ich den aktuellen Wert von eingeben, iwenn ich dazu aufgefordert werde.

(Übrigens, myprogramnimmt 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 ieingegeben 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 <<EOFam Ende der myprogram -optionsZeile 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 jto myprogrameingeben, aber der Wert von jkann sich zwischen dem Aufruf von myprogram -optionsund dem Ende der Datei ändern EOF.

Hast du irgendwelche Vorschläge?


Überprüfen Sie diesen Blog - Ausführen interaktiver Programme
Suresh

Antworten:


14

Für fast alle Programme funktionieren beide echo $i | myprogram -optionsund myprogram -options <<<$isollten funktionieren, indem das Programm $iüber die Standardeingabe eingespeist wird.

<fooverwendet den Inhalt der Datei mit dem Namen foostdin.

<<fooverwendet den Text zwischen diesem und einer Zeile, die ausschließlich fooals Standardeingabe besteht. Dies ist ein Dokument hier (Heredoc), wie Gilles sagte; EOFbedeutet eigentlich nicht das Ende der Datei, es ist nur ein üblicher Heredoc-Abgrenzer (in diesem Beispiel verwenden wir stattdessen "foo").

<<<fooverwendet 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.


9

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ä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: Es EOFist kein Schlüsselwort, es ist lediglich traditionell.

#!/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

Mit anderen Worten bedeutet EOF in diesem Zusammenhang eine Markierung für das Dateiende , nicht das eigentliche Ende der Skriptdatei. Der Text "EOF" ist ein beliebiger Text - was auch immer Sie unmittelbar nach den << Zeichen verwenden, zeigt das Ende des Here-Now-Dokuments an. Ich verwende normalerweise EOF, weil es auffällt und sehr unwahrscheinlich ist, dass es sich im folgenden Dokument befindet, wenn ich z. B. das Shell-Skript programmgesteuert generiere (was ich ziemlich oft mache).
Cas

das fettgedruckte EOF sollte <underscore> <underscore>EOF <underscore> <underscore> sein
cas

Mit solchen Dokumenten habe ich oft die Endmarkierung in etwas geändert, das viel aussagekräftiger ist (und weniger wahrscheinlich "zufällig" übereinstimmt), wie z 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.
Killermist

Wie können Sie sleepzwischen den Befehlen aus dem Skript lesen?
Boltup_im_coding

@ unerwartet62 Ich verstehe nicht, was du fragst. Sie sollten wahrscheinlich eine neue Frage auf dieser Seite stellen. Stellen Sie sicher, dass Sie genügend Kontext angeben.
Gilles 'SO - hör auf böse zu sein'

3

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.