Wenn eine Eingabedatei gesucht werden kann (wie das Lesen aus einer regulären Datei) oder nicht gesucht werden kann (wie das Lesen aus einer Pipe), sedverhalten sich (und andere Standarddienstprogramme) anders (siehe INPUT FILESAbschnitt in diesem Link ).
Zitat aus dem doc:
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.
Also in:
(sed '/y/ q'; echo aaa; cat) < test
sedausgeführt qes Datei am Anfang der Offset links uit vor dem Erreichen EOF gebiete, so zzzLinie, so catweiter die Linien bleiben Druck (GNU sed ist nicht POSIX - konform in einem gewissen Zustand, siehe unten).
Und weiter aus dem Dokument:
Bei nicht durchsuchbaren Dateien ist der Status des Dateioffsets in der Beschreibung der geöffneten Datei für diese Datei nicht angegeben
In diesem Fall ist das Verhalten nicht angegeben. Die meisten Standardwerkzeuge, einschließlich sed, verbrauchen die Eingabe so weit wie möglich. Es liest die yyyZeile durch und beendet sie, qohne den Dateiversatz wiederherzustellen, so dass nichts mehr übrig bleibt cat.
GNU sedist nicht standardkonform, abhängig von der stdio-Implementierung des Systems und der glibc-Version:
$ (gsed '/y/ q'; echo aaa; cat) < test
xxx
yyy
aaa
Hier wurde das Ergebnis von Mac OSX 10.11.6, virtuellen Maschinen Centos 7.2 - glibc 2.17, Ubuntu 14.04 - glibc 2.19 erhalten, die auf Openstack mit CEPH-Backend ausgeführt werden.
Auf diesen Systemen können Sie die -uOption verwenden, um das Standardverhalten zu erreichen:
(gsed -u '/y/ q'; echo aaa; cat) </tmp/test
und für Pfeife:
$ cat test | (gsed -u '/y/ q'; echo aaa; cat)
xxx
yyy
aaa
zzz
Dies führt zu einer schrecklich ineffizienten Leistung, da sedjeweils ein Byte gelesen werden muss. Eine Teilausgabe von strace:
$ strace -fe read sh -c '{ sed -u "/y/q"; echo aaa; cat; } <test'
...
[pid 5248] read(3, "", 4096) = 0
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
xxx
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
yyy
...
cat(in der Subshell) der Dateideskriptor im ersten Fall wiederverwendet werden kann, da stdin an eine echte Datei gebunden ist. Im zweiten Fall stammt stdin aus einer Pipe und nicht aus einer echten Datei. Beachten Sie, dass auch(sed '/y/ q'; echo aaa; cat) < <(cat test)nicht gedruckt wirdzzz.