2009-09-28 18 views
5

Ich habe ein Programm, das von Standardeingabe liest, wenn von der Befehlszeile aufgerufen. Normalerweise würde der Benutzer einige Informationen eingeben, C-d in einer neuen Zeile drücken, um das Ende der Datei anzuzeigen, und das Programm würde die Datei verarbeiten. Dann würde der Benutzer erneut aufgefordert werden, würde mehr Text eingeben und erneut C-d drücken, um das Ende der zweiten Datei zu signalisieren.Einreichung mehrerer Dateien aus Shell-Skript über Standardeingabe

Ich bin auf der Suche nach einem Shell-Skript, das dieses Programm aufruft und automatisch die zwei Dateien abschickt. Ich möchte so etwas wie dies tun:

$ myprogram < file1.txt < file2.txt 

ODER

$ myprogam <file1.txt file2.txt 

Irgendwelche Vorschläge? Ich benutze die Bash Shell unter Linux.

+0

Wie zeigt der Benutzer das Ende aller Dateien an? Zwei Control-Ds in einer Reihe? Der Standardentwurf für Unix-Programme lautet "Lese Dateien, die auf der Kommandozeile genannt werden; wenn es keine solchen Dateien gibt, verarbeite Standardeingabe". Wenn Sie dieses Design übernehmen, gibt es keine Probleme. Sie rufen einfach 'myprogram file1.txt file2.txt' auf. –

Antwort

0

Eine mögliche Sache zu tun wäre, expect zu verwenden.

3

Natürlich können Sie cat verwenden zwei Dateien in ein Programm Standardeingabe zu senden, aber das ist wahrscheinlich nicht das, was Sie wollen:

$ cat file1.txt file2.txt | myprogram 

Im obigen Fall myprogram nicht in der Lage sein zu sagen, wo file1.txt Enden und file2.txt beginnt, es sei denn, sie hatten bestimmte Formatierung und es beobachtete den Stream für bestimmte Formatierung, die das Ende oder den Anfang einer Datei bezeichnet.

Es gibt keinen Standardweg für das Senden mehrerer Streams an die Standardeingabe. Im Grunde genommen gibt es nur einen einzigen Stream, der in die Standardeingabe einfließt.

Sie würden Ihr Skript wahrscheinlich so strukturieren, dass es mehrere Argumente in der Befehlszeile akzeptiert und intern einzeln geöffnet und verarbeitet wird. Das heißt, würden Sie es wie so nennen:

$ myprogram file1.txt file2.txt 
+0

vielleicht gibt es eine Möglichkeit zu sagen: $ cat file1.txt "EOF" file2.txt und dann würde es wissen, dass es zwei separate Dateien ist? –

+0

Nein, es gibt keine Möglichkeit EOF so zu senden; Sehen Sie meine Kommentare zu Pavel Shveds Antwort. –

0

Jonathan Leffler in seinem Kommentar sagt, dass meine Lösung falsch ist. Vielleicht ist es. Ich habe es tatsächlich nicht gründlich überprüft. Aber lass es hier nur für Info sein, dass es zumindest eine falsche Antwort ist.


Bash kann mit dem Befehl echo ein Steuerzeichen ausgeben. EOF ist C-d, wie Sie bereits erwähnt haben, so lassen Sie sich ein Sub-Shell verwenden:

$ (cat file1.txt ; echo -e '\cD' ; cat file2.txt) | myprogram 

Diese Befehle innerhalb der Klammern und die Ausgabe der sie alle, als ob es ein separates Programm war ausgeführt wird.

Wenn Sie unsicher sind, dass sie Rohre richtig, versuchen Sie dies:

$ (echo "Hello" ; echo -e '\cD' ; echo "bash") | tee 
+1

Das Steuerelement-D wird vom Terminaltreiber abgefangen und sendet ausstehende Daten - keine Zeichen, wenn keine ausstehen. Das Programm erhält daher ein Null-Byte-Lesen, das EOF anzeigt. Das Echo von wörtlichen Kontroll-D-Zeichen in der Pipeline simuliert das nicht - es gibt keinen Terminaltreiber, der helfen könnte. Dort kommt 'expect' ins Spiel - es benutzt Pseudo-ttys, um Terminals zu emulieren. –

2

Hat es 1 Aufruf sein? Wenn nicht:

for file in file1 file2 file3; do myprogram < $file; done 
0

Ich habe ein einfaches Python-Programm geschrieben, um das Verhalten des von Ihnen beschriebenen Programms zu simulieren. Dies versetzt uns alle in die Lage, über das Mindeste zu reden, anstatt davon auszugehen, wie Ihr Programm funktioniert. (Natürlich, wenn Ihr Programm nicht so funktioniert, wie ich es hier beschrieben habe, bitte korrigieren Sie mich.

)
#!/usr/bin/python 

def read_a_file(): 
    print('Type the contents of a file now.') 
    while True: 
     try: 
      s = raw_input('>') 
     except EOFError: 
      break 

read_a_file() 
read_a_file() 
print('We have now read two files. Quitting.') 

Sie können dieses Skript auszuführen, geben Sie den Inhalt der ersten Datei, drücken Sie CTRL-D, um den Inhalt der zweiten Datei eingeben, drücken Sie CTRL-D, und das Programm beendet. Dies scheint das Verhalten zu sein, das Sie beschreiben.

Mein erster Gedanke war zu erwarten, wie das Chaos vorgeschlagen. Ich kann jedoch keine Unterstützung darin finden, den Inhalt einer Datei an einen Prozess zu übergeben. (Ich nehme an, die Inhalte der Dateien sind jedes Mal anders. Wenn sie gleich sind, dann würde erwarten, würde funktionieren, nur durch den Inhalt der Dateien in das Expect-Skript.)

Ich sollte beachten, dass ich bin keineswegs ein expect expert; es gibt vielleicht einen Weg, dies zu tun, was mir nicht klar ist.

Mein zweiter Gedanke war, ein Python-Skript zu schreiben, das Ihr Programm startete, und fütterte es den Inhalt der Dateien und der EOF-Zeichen. Jonathan Lefflers Kommentare ließen mich jedoch denken, dass Echo-EOF-Charaktere nicht funktionieren würden.

Mein dritter Gedanke ist verdammt kludgy. Sie könnten ein Skript schreiben, das ein expect-Skript erstellt, indem Sie den Inhalt der Dateien in das expect-Skript einbetten und dann das expect-Skript ausführen. Ich vermute, das würde funktionieren.