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), sed
verhalten sich (und andere Standarddienstprogramme) anders (siehe INPUT FILES
Abschnitt 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
sed
ausgeführt q
es Datei am Anfang der Offset links uit vor dem Erreichen EOF gebiete, so zzz
Linie, so cat
weiter 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 yyy
Zeile durch und beendet sie, q
ohne den Dateiversatz wiederherzustellen, so dass nichts mehr übrig bleibt cat
.
GNU sed
ist 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 -u
Option 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 sed
jeweils 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
.