Betrachten Sie die folgende Eingabedatei:
1
2
3
4
Laufen
{ grep -q 2; cat; } < infile
druckt nichts. Ich würde erwarten, dass es gedruckt wird
3
4
Ich kann die erwartete Ausgabe erhalten, wenn ich sie in ändere
{ sed -n 2q; cat; } < infile
Warum gibt der erste Befehl die erwartete Ausgabe nicht aus?
Es ist eine suchbare Eingabedatei und entspricht dem Standard unter OPTIONEN :
-q
Quiet. Nothing shall be written to the standard output, regardless of
matching lines. Exit with zero status if an input line is selected.
und weiter unten unter ANWENDUNGSVERWENDUNG (meine hervorheben):
Mit dieser
-q
Option können Sie auf einfache Weise feststellen, ob ein Muster (oder eine Zeichenfolge) in einer Gruppe von Dateien vorhanden ist. Beim Durchsuchen mehrerer Dateien wird eine Leistungsverbesserung erzielt ( da die Suche beendet werden kann, sobald die erste Übereinstimmung gefunden wird ). [...]
Jetzt nach dem gleichen Standard (in der Einleitung unter INPUT FILES )
Wenn ein Standarddienstprogramm eine suchbare Eingabedatei liest und ohne Fehler beendet, bevor das Dateiende erreicht ist, muss das Dienstprogramm sicherstellen, dass der Dateiversatz in der Beschreibung der geöffneten Datei genau hinter dem letzten vom Dienstprogramm verarbeiteten Byte [ positioniert ist . ..]
tail -n +2 file
(sed -n 1q; cat) < file
...
Der zweite Befehl entspricht nur dann dem ersten, wenn die Datei gesucht werden kann.
Warum grep -q
verbraucht die ganze Datei?
Dies ist, gnu grep
wenn es darauf ankommt (obwohl Kusalananda gerade bestätigt hat, dass dasselbe unter OpenBSD passiert)
grep
ist eine Abzweigung von etwas, das sich FreeGrep nennt , wenn sich jemand wundert.Antworten:
grep
hört zwar früh auf, puffert aber die Eingabe, sodass Ihr Test zu kurz ist (und ja, ich stelle fest, dass mein Test unvollständig ist, da er nicht suchbar ist):Startet bei 6776 auf meinem System. Das stimmt mit dem 32-KB-Puffer überein, der standardmäßig in GNU grep verwendet wird:
Ausgänge
Beachten Sie, dass POSIX nur Leistungsverbesserungen erwähnt
Das lässt keine Erwartungen an Leistungsverbesserungen aufgrund des teilweisen Lesens einer einzelnen Datei aufkommen.
quelle
Dies liegt offensichtlich an der Pufferung,
grep
die die Dinge beschleunigt. Es gibt Tools, die speziell dafür ausgelegt sind, so viele Zeichen wie gewünscht zu lesen und nicht mehr. Einer von ihnen istexpect
:Ich habe kein System, um das anzuprobieren, aber ich glaube,
expect
es frisst alles auf, bis es auf die erwartete Zeichenfolge (2
) stößt , und endet dann und lässt den Rest der Eingabe fürcat
.quelle
Sie sind sed und grep verwirrend.
Für den Befehl sed
-2q
heißt es, die aktuelle Iteration zu beenden, wenn in der zweiten Zeile die-n
Option "Leise arbeiten" angegeben ist, sodass nach der zweiten Zeile alle Zeilen angezeigt werden.Der Befehl grep wird standardmäßig ausgeführt, um alle übereinstimmenden Zeilen auszugeben. Die
-q
Option say gibt jedoch nichts an stdout aus. Wenn die Eingabe also eine "2" enthält, hat sie den Ausgangswert SUCCESS, andernfalls FAILURE. Was das ist, hängt von Ihrem Betriebssystem und der Shell ab. In der Regel können Sie also feststellen, ob eine Zeile übereinstimmt, indem Sie den Exit-Wert des grep-Prozesses untersuchen. Dies ist nützlich in einer Pipeline, in der Sie wissen möchten, ob Ihre Eingabe als Test einen Wert enthält. Z.BIn diesem Fall ist es uns wirklich egal, ob alle übereinstimmenden Zeilen angezeigt werden. Es ist uns nur wichtig, ob mindestens eine vorhanden ist. Der
report_crash_via_email
Prozess / die Funktion kann dann losgehen und die Datei erneut öffnen oder nicht.Wenn Sie möchten, dass Ihr grep-Prozess nach dem Finden des Zeichens "2" STOPPT - es wird nicht standardmäßig jede Zeile daraufhin überprüft, ob sie übereinstimmt - müssen Sie ihm dies mitteilen. Der Befehlszeilenschalter dafür ist
-m <value>
. Also für deinen Fallgrep -q -m1 2
.quelle
grep
aber bei dieser Frage geht es um etwas Feinsinnigeres und Esoterischeres. Anscheinend haben Sie die Frage zu schnell gelesen, um das tatsächlich abgefragte Verhalten zu verstehen. Außerdem stoppt GNUgrep
die Suche, wenn es mit-q
(wie im Zitat aus der POSIX-Spezifikation erlaubt) verwendet wird: Die Manpage für GNU grep gibt an, dass es "[s] sofort mit dem Status Null beendet, wenn eine Übereinstimmung gefunden wird" . FWIW, ich habe Ihre Frage bearbeitet, um zu zeigen, wie Sie zukünftige Beiträge formatieren können. Willkommen bei Stack Exchange .grep
wird gefragt, ob in der Datei '2' vorhanden ist, nicht mehr und nicht weniger. Bis zu diesem Punkt verhält es sich nicht wiesed
Aufzeichnungen und verbraucht sie und überlässt den Rest der Aufzeichnungen der weiteren Verarbeitung. Es liest, bis es weiß, dass es eine '2' gibt oder nicht, schließt die Datei und gibt das Ergebnis zurück.grep
Tatsächlich "verbraucht nur die gesamte Datei" (ohne Berücksichtigung von Überlegungen zum Puffern), wenn die Suchzeichenfolge in der Datei nicht vorhanden ist (was nur durch Untersuchen der gesamten Datei bewiesen werden kann). Wenn dies nicht der Fall ist, stoppt das Lesen der Datei , die Datei wird geschlossen und SUCCESS wird zurückgegeben.