Warum unterscheidet sich das Entnehmen von stdin aus einer Datei davon, es über eine Pipe zu empfangen?

8

Mit bash möchte ich oft die Überschriften einer großen CSV-Datei erhalten und den Rest nach einem bestimmten Eintrag durchsuchen. Ich mache das wie folgt.

%Vor%

Aber die Eingabe von cat oder einem anderen Befehl funktioniert nicht - es scheint, dass grep niemals den Rest der Datei passiert.

%Vor%

Warum gibt es in diesen beiden Fällen ein unterschiedliches Verhalten?

    
tlrrd 27.01.2012, 12:45
quelle

3 Antworten

7

Der Unterschied zwischen dem Lesen aus einer Pipe und dem Lesen aus einer Datei besteht darin, dass Sie lseek für eine Datei, aber nicht für eine Pipe verwenden können.

Das Verhalten hier sieht (wie durch strace gesehen) aus, als käme es von head , nicht bash. head liest einen Puffer und findet die entsprechende Anzahl von Zeilen, dann lseek rückwärts bis zu dem Punkt, an dem die Zeile mit der letzten Ausgabe endete, wobei das Datei-Handle an dieser Stelle offen bleibt. Wie oben funktioniert das, wenn es eine Datei liest, aber nicht, wenn es von einer Pipe liest.

Ich kann mir keinen Fall vorstellen anderen als das, was Sie tun, wo dieses Verhalten in head sinnvoll ist, aber da ist es. Lerne jeden Tag etwas Neues, ich sage dir ...

    
evil otto 27.01.2012, 18:29
quelle
3

Sehr seltsam. Sie sollten sich nicht auf dieses undokumentierte Verhalten verlassen, sondern stattdessen Folgendes verwenden:

%Vor%     
choroba 27.01.2012 13:53
quelle
0

Ich kann das mit bash 3.2.48 nicht zuverlässig reproduzieren. Beide sind erfolgreich oder beide Fehler. Der Grund für die Fehler ist jedoch, wie groß die Datei ist.

cat liest einen Puffer (4k-64k je nach System) und gibt es in die Pipe. head verbraucht den gesamten Puffer und endet dann. grep hat dann Zugriff auf die Datei nach der Puffergröße. Auf meinem System kann ich deine Pipe nur zu grep thing weiter als einen Puffer in die Datei einfügen (so kann ich grep sachen am Ende einer langen Datei, aber nicht am Anfang nach der Verwendung von head ).

Es ist möglich, dass spätere Versionen von bash den Operator < optimieren (aber nicht cat ), damit Ihr Trick funktioniert, aber ich glaube nicht, dass dies ein unterstütztes Verhalten ist.

    
Rob Napier 27.01.2012 13:10
quelle

Tags und Links