2010-11-03 8 views
6

Ich habe ein Befehlszeilen-Dienstprogramm von einer dritten Partei (es ist groß und in Java geschrieben), die ich verwendet habe, um mir zu helfen, einige Daten zu verarbeiten. Dieses Dienstprogramm erwartet Informationen in einer Datei mit Zeilenbegrenzung und gibt dann verarbeitete Daten an STDOUT aus.Gibt es eine Möglichkeit, stdin/out anstelle einer Datei zu einem Programm in Unix zu liefern?

In meinen Testphasen ging es mir gut, etwas Perl zu schreiben, um eine Datei voller Informationen zu erstellen und diese Datei an dieses Drittanbieter-Dienstprogramm zu senden, aber als ich diesen Code in Produktion bringe, würde ich würde es wirklich bevorzugen, Daten direkt an dieses Dienstprogramm zu leiten, anstatt zuerst diese Daten in eine Datei zu schreiben, da dies mir den Aufwand ersparen würde, nicht benötigte Informationen auf die Festplatte zu schreiben. Gibt es eine Möglichkeit, dies in Unix zu tun?

Zur Zeit nenne ich das Dienstprogramm wie folgt:

bin/someapp do-action --option1 some_value --input some_file

ich, wie etwas tun möchte:

bin/someapp do-action --option1 some_value --input $piped_in_data

alles ist wie das möglich, ohne meine den Dritten zu modifizieren App?

+0

Es gibt eine viel umfassendere Antwort auf StackExchange, siehe . – weynhamz

Antwort

10

Sie sollten in der Lage sein/verwenden dev/stdin:

bin/someapp do-action --option1 some_value --input /dev/stdin 

(Beachten Sie, dass auf manchen Systemen,/dev/stdin ist ein symbolischer Link, wenn Ihr Java-Programm nicht damit fertig ist, können Sie muss stattdessen/dev/fd/0 oder etwas Ähnliches verwenden.)

+0

Also an welchem ​​Punkt würde ich dann die Daten an Stdin senden? Würde es darauf warten, nachdem ich das angerufen habe? Oder würde ich es sofort vor der Hand machen? Wie genau würde das funktionieren? – Eli

+0

Verwenden Sie es in einer normalen Pipeline: 'generate_data.pl | bin/someapp do-aktion --option1 some_value --input/dev/stdin' –

+0

Ehrfürchtig. Das ist genau das, was ich wollte. – Eli

10

Sie können "Prozesssubstitution" in Bash verwenden, um etwas zu erreichen, was Sie wollen.

bin/someapp do-action --option1 some_value --input <(generate_input.sh) 

sollte den Trick tun. Der <(list) Teil ist die Prozesssubstitution.

+0

Süß! Gibt es eine Möglichkeit, ein Perl-Skript dort zu verwenden? Um zu testen, habe ich versucht: echo <(perl -e 'print "yo;"'), aber das schien nicht zu funktionieren. – Eli

+0

versuche stattdessen: cat - <<(perl -le 'print "yo"') :) – pavel

+0

Oder einfach nur 'cat <(perl was auch immer)'. Das Bit <(...) wird durch den Namen einer Datei ersetzt, die eine Pipe für die generierten Daten darstellt. echo weiß nichts über das Lesen von Dateien, aber 'cat' tut es. –

2

Eine andere Route, wenn die /dev/stdin Technik aus irgendeinem Grund nicht geeignet ist, ist die Verwendung einer "Named Pipe".

Wenn Sie das tun

% mkfifo /path/to/file 

dann wird dies mit diesem Namen ein Dateisystem-Objekt erstellen, die als eine Leitung zwischen zwei Prozessen wirken können. Dies ist genau das Gleiche wie bei einer normalen Pipe, außer dass Prozesse sich auf die Pipe beziehen können, als ob es eine normale Datei wäre. Zum Beispiel:

% mkfifo /tmp/my-fifo 
% grep alias ~/.bashrc >/tmp/my-fifo & 
[1] 70134 
% sed 's/alias/wibble/' /tmp/my-fifo 
wibble ls='ls -F' 
.... 
[1] + done  grep alias ~/.bashrc > /tmp/my-fifo 
% 

Hier wird der grep Befehl an den FIFO-Schreiben genauso, als ob es sich um eine normale Datei waren, und es blockiert, wenn der Puffer des Named Pipe füllt. Der Prozess sed liest aus der Pipe (als wäre es eine normale Datei) und leert dabei den Puffer.

2

Es ist nicht so einfach./dev/stdin, named pipes und <() process substitution wird von einem Programm nicht auf dieselbe Weise wie eine Datei aufgerufen. Insbesondere ist es nicht möglich, innerhalb eines solchen Konstrukts fseek(), fsetpos() zu verwenden, da dessen Länge nicht a priori bekannt ist.

Einige Funktionen wie fopen(), getc(), fread() usw. funktionieren jedoch. Für die meisten Programme, die Zeile für Zeile oder Zeile für Zeile lesen, ist dies der Fall.

Wenn Ihr Programm innerhalb einer Datei sucht (und möglicherweise andere "erweiterte" Operationen), müssen Sie leider eine temporäre Datei erstellen.

Verwandte Themen