Lesen Sie zuerst eine Zeile aus stdin:
IFS= read -r line if [[ -n "$line" ]]; then # the line is non-empty. # add the line back into the stream and pipe it into your program { echo "$line"; cat -; } | your_program fi
Ich möchte zu tun:
if not eof(stdin): pass stdin to program else: do nothing
Ich habe das Gefühl, dass es ziemlich nahe an Folgendes geschrieben werden kann:
if test ! --is-eof - ; then exec program
Das Problem, das ich zu lösen versuche, ist, dass es program
von stdin liest, aber abstürzt, wenn es keine Eingabe erhält. Ich habe keinen Zugriff auf die Quelle für die program
so program
nicht geändert werden kann. Die Binäreingabe ist größer als der Speicher, daher ist es inakzeptabel langsam, stdin zuerst in eine Datei zu setzen. Die zeilenweise Verarbeitung der Eingabe in der Bash ist inakzeptabel langsam.
Die Lösung sollte idealerweise unter csh und bash funktionieren.
Lesen Sie zuerst eine Zeile aus stdin:
IFS= read -r line if [[ -n "$line" ]]; then # the line is non-empty. # add the line back into the stream and pipe it into your program { echo "$line"; cat -; } | your_program fi
Dies scheint sowohl in csh als auch in bash zu funktionieren und eignet sich gut für die Binäreingabe (auch \ 0 als erstes Zeichen):
# Set $_FIRST_CHAR_FILE to the name of a temp file. eval `echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv _FIRST_CHAR_FILE /tmp/$$.first_char_file || echo export _FIRST_CHAR_FILE=/tmp/$$.first_char_file` dd bs=1 count=1 of=$_FIRST_CHAR_FILE >&/dev/null test -s "$_FIRST_CHAR_FILE" && ( cat $_FIRST_CHAR_FILE; rm $_FIRST_CHAR_FILE; cat - ) | program
Danke an @ glenn-jackman für die Idee, etwas zu lesen, bevor Sie dies und den Rest von stdin durchgehen cat
.
Welche Art von Input erwartet Ihr Programm? Leiten Sie die Ausgabe von einem Programm zum anderen oder lesen Sie eine Datei?
Wenn Sie die Pipe-Umleitung zum Erfassen von Eingaben für Ihr Skript verwenden, wird die Ausführung so lange ausgeführt, bis die Eingabe bereitgestellt wird.
Wenn Sie versuchen, aus einer Datei zu lesen, verwenden Sie "while" oder "bis", um die Aufgabe auszuführen.
Ich poste hier, da diese nach oben kamen bei der Suche und da es mir geholfen, das Debuggen auf Darwin (Snow Leopard) bash in set -x;trap 'test -s /dev/stdin||exit' debug
ein Gespräch zu finden, die den geerbte Eingang des übergeordneten Skript verzehrte.
Für schwache Nerven:
if [[ -s /dev/fd/0 ]] then echo 'Not at EOF' else echo 'Currently no input to read' fi
echo $((echo|test -s /dev/stdin)&&! (true|test -s /dev/stdin)&&echo pass||echo fail) $
Der obige Test ergibt Folgendes in meinen bash-Versionen und -Systemen.
pass 4 2 45 2 release i386-apple-darwin10.8.0
pass 3 2 48 1 release x86_64-apple-darwin10.0
fail 4 2 37 1 release x86_64-pc-linux-gnu
Das Piping cat /proc/self/fdinfo/0
auf mein Debian (Wheezy) gibt nichts zu testen.
CheerIO oder besser cheerEO für fehlerhaft / Output%)
Wenn Sie nicht möchten, dass Ihr Skript bei dem Versuch blockiert, nach etwas zu suchen, das Sie lesen möchten, können Sie (zumindest in bash) einen Read mit Timeout verwenden
$ ( read -t 0 var ; echo $? ) 1 $ echo foo | ( read -t 0 var ; echo $? ) 0
Dies garantiert jedoch nicht, dass Sie über EOF verfügen, dass Sie jedoch momentan nichts lesen können