Dies ist wahrscheinlich in vielen FAQs - anstatt zu verwenden:
cat file | command
(was als nutzloser Gebrauch von Katze bezeichnet wird), korrekter Weg soll sein:
command < file
Auf die zweite, "richtige" Weise - das Betriebssystem muss keinen zusätzlichen Prozess erzeugen.
Obwohl ich das wusste, benutzte ich aus zwei Gründen weiterhin nutzlose Katzen.
ästhetischer - Ich mag es, wenn sich Daten nur von links nach rechts gleichmäßig bewegen. Und es leichter zu ersetzen
cat
mit etwas anderem (gzcat
,echo
, ...), fügen Sie eine zweite Datei oder fügen Sie neue Filter (pv
,mbuffer
,grep
...).Ich "fühlte", dass es in einigen Fällen schneller sein könnte. Schneller, weil es 2 Prozesse gibt, 1. (
cat
) liest und der zweite macht was auch immer. Und sie können parallel ausgeführt werden, was manchmal eine schnellere Ausführung bedeutet.
Ist meine Logik korrekt (aus dem 2. Grund)?
quelle
cat
ist eine Identitätspfeife . Es überträgt nur seine Eingabe auf seine Ausgabe. Wenn das zweite Programm in der Kette seine Eingabe von demselben Argument übernehmen kann, an das Sie übergebencat
(oder von der Standardeingabe, wenn Sie kein Argument übergeben),cat
ist dies absolut nutzlos und führt nur dazu, dass ein zusätzlicher Prozess gegabelt wird und eine zusätzliche Pipe vorhanden ist erstellt.-
, ist es eine Identitätspipe. Wenn es mehr als ein Nicht-Bindestrich-Dateinamenargument hat, wird es jedoch mehr als eine Identitätspipe und beginnt, einen echten Zweck zu erfüllen.<file command1 | command2
, obwohl es Unstimmigkeiten über die Ästhetik geben würde.Antworten:
Ich war mir der Auszeichnung erst heute bewusst, als ein Neuling versuchte, mir die UUOC für eine meiner Antworten zuzuweisen. Es war ein
cat file.txt | grep foo | cut ... | cut ...
. Ich gab ihm einen Teil meiner Gedanken und erst nachdem ich den Link besucht hatte, gab er mir einen Hinweis auf die Ursprünge der Auszeichnung und die Praxis, dies zu tun. Weitere Suche führte mich zu dieser Frage. Trotz bewusster Überlegung enthielt leider keine der Antworten meine Begründung.Ich hatte nicht vorgehabt, defensiv auf ihn zu reagieren. Schließlich hätte ich in meinen jüngeren Jahren den Befehl so geschrieben, als
grep foo file.txt | cut ... | cut ...
ob Sie, wenn Sie die häufigen Single-grep
s machen, die Platzierung des Dateiarguments lernen und es ist bekannt, dass das erste das Muster und die späteren Dateinamen sind.Es war eine bewusste Entscheidung,
cat
als ich die Frage beantwortete, teilweise aus einem Grund des "guten Geschmacks" (in den Worten von Linus Torvalds), aber hauptsächlich aus einem zwingenden Grund der Funktion.Der letztere Grund ist wichtiger, deshalb werde ich ihn zuerst herausstellen. Wenn ich eine Pipeline als Lösung anbiete, erwarte ich, dass sie wiederverwendbar ist. Es ist sehr wahrscheinlich, dass eine Pipeline am Ende einer anderen Pipeline hinzugefügt oder in eine andere Pipeline gespleißt wird. In diesem Fall beeinträchtigt ein Dateiargument für grep die Wiederverwendbarkeit und dies möglicherweise stillschweigend ohne Fehlermeldung, wenn das Dateiargument vorhanden ist. I. e.
grep foo xyz | grep bar xyz | wc
gibt an, wie viele Zeilenxyz
enthalten sind,bar
während Sie die Anzahl der Zeilen erwarten, die sowohlfoo
als als auch enthaltenbar
. Das Ändern von Argumenten in einen Befehl in einer Pipeline, bevor dieser verwendet wird, ist fehleranfällig. Fügen Sie die Möglichkeit stiller Ausfälle hinzu und es wird eine besonders heimtückische Praxis.Der erstere Grund ist auch nicht unwichtig, da viel " guter Geschmack " lediglich eine intuitive unbewusste Begründung für Dinge wie die oben genannten stillen Fehler ist, an die Sie nicht denken können, wenn eine bildungsbedürftige Person sagt ", aber nicht diese Katze nutzlos ".
Ich werde jedoch versuchen, auch den früheren Grund für den "guten Geschmack", den ich erwähnt habe, bewusst zu machen. Dieser Grund hat mit dem orthogonalen Designgeist von Unix zu tun.
grep
nichtcut
undls
nichtgrep
. Das widerspricht zumindestgrep foo file1 file2 file3
dem Designgeist. Die orthogonale Vorgehensweise istcat file1 file2 file3 | grep foo
. Jetztgrep foo file1
ist nur ein Sonderfall vongrep foo file1 file2 file3
, und wenn Sie es nicht gleich behandeln, verbrauchen Sie zumindest Gehirnuhrzyklen, um den nutzlosen Katzenpreis zu vermeiden.Das führt uns zu dem Argument,
grep foo file1 file2 file3
das verkettet undcat
verkettet, so dass es angemessen ist,cat file1 file2 file3
aber weilcat
es nicht verkettet,cat file1 | grep foo
verletzen wir den Geist sowohl descat
als auch des allmächtigen Unix. Wenn dies der Fall wäre, würde Unix einen anderen Befehl benötigen, um die Ausgabe einer Datei zu lesen und in stdout zu spucken (nicht paginieren oder irgendetwas anderes, nur in stdout spucken). Sie hätten also die Situation, in der Sie sagencat file1 file2
oder sagen,dog file1
und denken Sie gewissenhaft daran, zu vermeidencat file1
, dass Sie die Auszeichnung nicht erhalten, und vermeiden Sie dies,dog file1 file2
da das Design von hoffentlichdog
einen Fehler auslösen würde, wenn mehrere Dateien angegeben werden.Hoffentlich sympathisieren Sie an dieser Stelle mit den Unix-Designern dafür, dass sie keinen separaten Befehl zum Spucken einer Datei an stdout enthalten und gleichzeitig
cat
nach Verkettung benennen, anstatt ihr einen anderen Namen zu geben.<edit>
Das Entfernen falscher Kommentare zu<
ist in der Tat<
eine effiziente No-Copy-Funktion, mit der eine Datei an stdout gespuckt werden kann, die Sie am Anfang einer Pipeline positionieren können, sodass die Unix-Designer etwas speziell dafür aufgenommen haben</edit>
Die nächste Frage ist, warum es wichtig ist, Befehle zu haben, die lediglich eine Datei spucken oder mehrere Dateien ohne weitere Verarbeitung zu stdout verketten. Ein Grund besteht darin, zu vermeiden, dass jeder einzelne Unix-Befehl, der mit Standardeingaben arbeitet, weiß, wie mindestens ein Befehlszeilendateiargument analysiert und als Eingabe verwendet wird, falls vorhanden. Der zweite Grund besteht darin, zu vermeiden, dass Benutzer sich erinnern müssen: (a) wohin die Dateinamenargumente gehen; und (b) den oben erwähnten stillen Pipeline-Fehler vermeiden.
Das bringt uns zu dem Grund, warum
grep
es die zusätzliche Logik gibt. Das Grundprinzip besteht darin, die Benutzerfreundlichkeit für Befehle zu ermöglichen, die häufig und eigenständig verwendet werden (und nicht als Pipeline). Es ist ein leichter Kompromiss der Orthogonalität für einen signifikanten Gewinn an Benutzerfreundlichkeit. Nicht alle Befehle sollten auf diese Weise entworfen werden, und Befehle, die nicht häufig verwendet werden, sollten die zusätzliche Logik von Dateiargumenten vollständig vermeiden (denken Sie daran, dass zusätzliche Logik zu unnötiger Fragilität führt (die Möglichkeit eines Fehlers)). Die Ausnahme besteht darin, Dateiargumente wie im Fall von zuzulassengrep
. (Übrigens, beachten Sie, dass diesls
einen ganz anderen Grund hat , Dateiargumente nicht nur zu akzeptieren, sondern auch zu erfordern.)Schließlich hätte es besser gemacht werden können, wenn solche außergewöhnlichen Befehle wie
grep
(aber nicht unbedingtls
) einen Fehler erzeugen, wenn die Standardeingabe auch verfügbar ist, wenn Dateiargumente angegeben werden.quelle
grep
Aufrufen mit mehreren Dateinamen den gefundenen Zeilen der Name der Datei vorangestellt wird, in der sie gefunden wurden (es sei denn, Sie deaktivieren dieses Verhalten). Es kann auch die Zeilennummern in den einzelnen Dateien melden. Wenn Sie nurcat
zum Füttern verwendengrep
, verlieren Sie die Dateinamen und die Zeilennummern sind über alle Dateien hinweg fortlaufend, nicht pro Datei. Daher gibt es Gründe,grep
mehrere Dateien selbst zu verarbeiten,cat
die nicht verarbeitet werden können. Die Einzeldatei- und Nulldateifälle sind lediglich Sonderfälle der allgemeinen Mehrdateienutzung vongrep
.< file command1 ...
. Obwohl die herkömmliche Position für die E / A-Umleitungsoperatoren nach dem Befehlsnamen und seinen Argumenten liegt, ist dies nur die Konvention und keine obligatorische Platzierung. Das<
muss vor dem Dateinamen stehen. Es gibt also eine nahezu perfekte Symmetrie zwischen>output
und<input
Umleitungen :<input command1 -opt 1 | command2 -o | command3 >output
.cat
das nutzlos ist. Es ist nicht so, dasscat
es nutzlos ist; Es ist so, dass ein bestimmtes Konstrukt nicht die Verwendung von benötigtcat
. Wenn Sie möchten , beachten Sie, dass es sich um UUoC (nutzlose Verwendung voncat
) und nicht um UoUC (nutzlose Verwendung voncat
) handelt. Es gibt viele Fälle, in denencat
das richtige Werkzeug verwendet wird. Ich habe kein Problem damit, dass es verwendet wird, wenn es das richtige Werkzeug ist (und erwähne in meiner Antwort tatsächlich einen Fall).cat
in der Pipe abhängig von den Daten möglicherweise keine große Sache. Bei Verwendung als Programmierumgebung kann es jedoch unbedingt erforderlich sein, diese leistungskritischen Dinge zu implementieren. vor allem, wenn es darum geht, was in Bezug aufbash
die Leistung wie ein rechteckig geformtes Rad ist (im Vergleich zuksh
sowieso. Ich spreche hier bis zu 10x langsamer - kein Scherz). Sie haben wollen , um Ihre Gabeln (und nicht nur das) zu optimieren , wenn mit größeren Skripten oder großen Schleifen zu tun.Nee!
Zunächst spielt es keine Rolle, wo in einem Befehl die Umleitung erfolgt. Wenn Sie also Ihre Umleitung links von Ihrem Befehl mögen, ist das in Ordnung:
ist das gleiche wie
Zweitens gibt es n + 1 Prozesse und eine Unterschale, wenn Sie eine Pipe verwenden. Es ist entschieden langsamer. In einigen Fällen wäre n Null gewesen (z. B. wenn Sie zu einer integrierten Shell umleiten). Wenn Sie also verwenden
cat
, fügen Sie einen neuen Prozess völlig unnötig hinzu.Als Verallgemeinerung lohnt es sich, wenn Sie ein Rohr verwenden, 30 Sekunden zu nehmen, um zu sehen, ob Sie es beseitigen können. (Aber es lohnt sich wahrscheinlich nicht, länger als 30 Sekunden zu dauern.) Hier einige Beispiele, bei denen Rohre und Prozesse häufig unnötig verwendet werden:
Fühlen Sie sich frei zu bearbeiten, um weitere Beispiele hinzuzufügen.
quelle
< cat grep dog
Dies ist ein erfundenes Beispiel, das zeigt, dass Sie nicht einfach zwischen der Eingabedatei und dem Befehl unterscheiden können das empfängt die Eingabe und die Argumente für den Befehl.stdout=$(foo bar -exec baz <qux | ENV=VAR quux)
. F : Hat<qux
geltenfoo
, oderbaz
, das ist-exec
‚d durchfoo
? A. Es gilt fürfoo
, kann aber mehrdeutig erscheinen. Putting ,<qux
bevorfoo
in diesem Fall ist klarer, wenn auch weniger häufig, und ist an den hinteren analogENV=VAR quux
.<"cat" grep dog
ist dort leichter zu lesen. (Ich bin normalerweise Pro-Whitespace, aber dieser spezielle Fall ist eine Ausnahme).Ich bin mit den meisten Fällen des übermäßig selbstgefälligen UUOC-Preises nicht einverstanden, da er beim Unterrichten eines anderen
cat
ein geeigneter Platzhalter für jeden Befehl oder jede knusprige, komplizierte Pipeline von Befehlen ist, die eine Ausgabe liefern, die für das besprochene Problem oder die diskutierte Aufgabe geeignet ist.Dies gilt insbesondere für Sites wie Stack Overflow, ServerFault, Unix & Linux oder eine der SE-Sites.
Wenn jemand speziell nach der Optimierung fragt oder wenn Sie zusätzliche Informationen hinzufügen möchten, sprechen Sie darüber, wie ineffizient die Verwendung von Katzen ist. Aber beschimpfen Sie die Leute nicht, weil sie sich dafür entschieden haben, in ihren Beispielen Einfachheit und Verständlichkeit anzustreben, anstatt mich anzuschauen, wie cool ich bin! Komplexität.
Kurz gesagt, weil Katze nicht immer Katze ist.
Auch, weil die meisten Leute, die gerne UUOCs vergeben, dies tun, weil sie mehr daran interessiert sind, zu zeigen, wie „klug“ sie sind, als Menschen zu helfen oder sie zu unterrichten. In Wirklichkeit zeigen sie, dass sie wahrscheinlich nur ein weiterer Neuling sind, der einen winzigen Stock gefunden hat, mit dem er seine Kollegen schlagen kann.
Aktualisieren
Hier ist eine weitere UUOC, die ich in einer Antwort unter https://unix.stackexchange.com/a/301194/7696 gepostet habe :
UUOC-Pedanten würden sagen, dass dies ein UUOC ist, da es leicht möglich ist,
$filter
die leere Zeichenfolge als Standard festzulegen und dieif
Anweisung zu tun,filter='| grep -v "^$"'
aber IMO, indem das Pipe-Zeichen nicht eingebettet wird$filter
, dient dieses "nutzlose"cat
dem äußerst nützlichen Zweck, die Tatsache selbst zu dokumentieren Das$filter
in derprintf
Zeile ist nicht nur ein weiteres Argumentsqlplus
, sondern ein optionaler vom Benutzer auswählbarer Ausgabefilter.Wenn es erforderlich ist , mehrere optionalen Ausgabefilter haben, könnte die Option Verarbeitung nur append
| whatever
zu$filter
so oft wie nötig - ein extracat
in der Pipeline wird nicht weh tut nichts oder verursacht eine merklichen Leistungseinbußen.quelle
==
inside[ ]
wird von POSIX nicht angegeben, und nicht alle Implementierungen akzeptieren dies. Der standardisierte Operator ist gerecht=
.Bei der UUoC-Version
cat
muss die Datei in den Speicher eingelesen und dann in die Pipe geschrieben werden, und der Befehl muss die Daten aus der Pipe lesen, sodass der Kernel die gesamte Datei drei kopieren muss Mal während im umgeleiteten Fall Der Kernel muss die Datei nur einmal kopieren. Es ist schneller, etwas einmal als dreimal zu tun.Verwenden von:
ist eine ganz andere und nicht unbedingt nutzlose Verwendung von
cat
. Es ist immer noch nutzlos, wenn der Befehl ein Standardfilter ist, der null oder mehr Dateinamenargumente akzeptiert und diese nacheinander verarbeitet. Betrachten Sie dentr
Befehl: Es ist ein reiner Filter, der Dateinamenargumente ignoriert oder ablehnt. Um mehrere Dateien zu füttern, müssen Siecat
wie gezeigt verwenden. (Natürlich gibt es eine separate Diskussion, deren Designtr
nicht sehr gut ist. Es gibt keinen wirklichen Grund, warum es nicht als Standardfilter entworfen werden könnte.) Dies kann auch gültig sein, wenn der Befehl alle Eingaben als behandeln soll einzelne Datei statt als mehrere separate Dateien, selbst wenn der Befehl mehrere separate Dateien akzeptieren würde: Dieswc
ist beispielsweise ein solcher Befehl.Es ist der
cat single-file
Fall, der bedingungslos nutzlos ist.quelle
Zur Verteidigung der Katze:
Ja,
oder
ist effizienter, aber viele Aufrufe haben keine Leistungsprobleme, sodass es Ihnen egal ist.
ergonomische Gründe:
Wir sind es gewohnt, von links nach rechts zu lesen, also ein Befehl wie
ist trivial zu verstehen.
muss über process1 springen und dann von links nach rechts lesen. Dies kann geheilt werden durch:
sieht irgendwie so aus, als ob ein Pfeil nach links zeigt, wo nichts ist. Verwirrender und sieht aus wie ausgefallenes Zitieren:
und das Generieren von Skripten ist oft ein iterativer Prozess.
wo Sie Ihren Fortschritt schrittweise sehen, während
funktioniert nicht einmal. Einfache Methoden sind weniger fehleranfällig und die ergonomische Befehlsverkettung ist bei cat einfach.
Ein weiteres Thema ist, dass die meisten Menschen lange vor der Verwendung eines Computers und bei der Verwendung eines Computers als Programmierer> und <als Vergleichsoperatoren ausgesetzt waren und diesen als solche weitaus häufiger ausgesetzt waren.
Der Vergleich zweier Operanden mit <und> ist kontrakommutativ, was bedeutet
Ich erinnere mich an das erste Mal, als ich <für die Umleitung von Eingaben verwendete, befürchtete ich
könnte das gleiche bedeuten wie
und überschreibe irgendwie mein a.sh Skript. Vielleicht ist dies ein Problem für viele Anfänger.
seltene Unterschiede
Letzteres kann direkt in Berechnungen verwendet werden.
Natürlich kann hier auch das <anstelle eines Dateiparameters verwendet werden:
aber wen interessiert das - 15k?
Wenn ich gelegentlich auf Probleme stoßen würde, würde ich sicherlich meine Gewohnheit ändern, Katzen anzurufen.
Wenn Sie sehr große oder viele, viele Dateien verwenden, ist es in Ordnung, cat zu vermeiden. Bei den meisten Fragen ist die Verwendung von Katze orthogonal, kein Thema, kein Problem.
Es ist nur ärgerlich und langweilig, diese nutzlose nutzlose Verwendung der Katzendiskussion zu jedem zweiten Shell-Thema zu beginnen. Holen Sie sich ein Leben und warten Sie auf Ihre Minute des Ruhms, wenn Sie sich mit Leistungsfragen befassen.
quelle
file > a.sh
ist allein die Zeit wert, dies zu lesen :) Vielen Dank für das Teilen!cat file | wc -c
,wc
bis EOF lesen muss stdin, Zählen Bytes. Aber in diesemwc -c < file
Fall wird nur stdin angezeigt, es wird herausgefunden, dass es sich um eine reguläre Datei handelt, und es wird st_size gedruckt, anstatt Eingaben zu lesen. Bei einer großen Datei wäre der Leistungsunterschied deutlich sichtbar.Ein weiteres Problem besteht darin, dass das Rohr eine Unterschale stillschweigend maskieren kann. Für dieses Beispiel werde ich ersetzen
cat
mitecho
, aber das gleiche Problem existiert.Sie könnten erwarten,
x
zu enthaltenfoo
, aber es tut nicht. Das vonx
Ihnen festgelegte wurde in einer Subshell erzeugt, um diewhile
Schleife auszuführen .x
In der Shell, die die Pipeline gestartet hat, hat die Pipeline einen nicht verwandten Wert oder ist überhaupt nicht festgelegt.In bash4 können Sie einige Shell-Optionen so konfigurieren, dass der letzte Befehl einer Pipeline in derselben Shell ausgeführt wird wie derjenige, der die Pipeline startet. Dann können Sie dies jedoch versuchen
und
x
ist wieder lokal für diewhile
Unterschale des.quelle
shopt -s lastpipe
das Erstellen der Subshell vermeiden.Als jemand, der regelmäßig auf dieses und eine Reihe anderer Antipattern für die Shell-Programmierung hinweist, fühle ich mich verpflichtet, verspätet abzuwägen.
Shell-Skript ist eine Kopier- / Einfügesprache. Für die meisten Leute, die Shell-Skripte schreiben, sind sie nicht darin, die Sprache zu lernen; Es ist nur ein Hindernis, das sie überwinden müssen, um weiterhin Dinge in der Sprache (n) zu tun, mit der sie tatsächlich etwas vertraut sind.
In diesem Zusammenhang sehe ich es als störend und möglicherweise sogar destruktiv an, verschiedene Shell-Scripting-Anti-Patterns zu verbreiten. Der Code, den jemand bei Stack Overflow findet, sollte idealerweise mit minimalen Änderungen und unvollständigem Verständnis in seine Umgebung kopiert / eingefügt werden können.
Unter den vielen Shell-Skriptressourcen im Internet ist der Stapelüberlauf insofern ungewöhnlich, als Benutzer die Qualität der Website durch Bearbeiten der Fragen und Antworten auf der Website verbessern können. Allerdings Code Änderungen können problematisch sein , , weil es einfach Änderungen vornehmen, die nicht durch den Code Autor bestimmt waren. Daher neigen wir dazu, Kommentare zu hinterlassen, um Änderungen am Code vorzuschlagen.
Die UUCA und verwandte Antimuster-Kommentare sind nicht nur für die Autoren des Codes bestimmt, den wir kommentieren. sie sind genauso ein Vorbehalt , um den Lesern zu helfen der Website zu , auf Probleme im Code aufmerksam zu werden, den sie hier finden.
Wir können nicht hoffen, eine Situation zu erreichen, in der keine Antworten auf Stack Overflow nutzlose
cat
s (oder nicht zitierte Variablen oder) empfehlenchmod 777
oder eine Vielzahl anderer Antipattern-Plagen) , aber wir können zumindest dazu beitragen, den Benutzer aufzuklären, der kopieren soll / Fügen Sie diesen Code in die innerste enge Schleife ihres Skripts ein, die millionenfach ausgeführt wird.Aus technischen Gründen ist die traditionelle Weisheit, dass wir versuchen sollten, die Anzahl externer Prozesse zu minimieren. Dies gilt weiterhin als gute allgemeine Anleitung beim Schreiben von Shell-Skripten.
quelle
cat
eine Menge zusätzlicher Kontextwechsel und Speicherbandbreite (und die Verschmutzung des L3-Cache durch zusätzliche Kopien von Daten imcat
Lesepuffer und den Pipe-Puffern). Insbesondere auf einem großen Multi-Core-Computer (wie bei vielen Hosting-Setups) ist die Cache- / Speicherbandbreite eine gemeinsam genutzte Ressource.bzip2
undgzip
Komprimierung sind beide sehr langsam im Vergleich zu dem Overheadcat
, der allein dazu beiträgt (wenn die Maschine ansonsten im Leerlauf ist). Es ist schwer, Ihre Tabellen zu lesen (Zeilenumbruch in der Mitte einer Zahl?).sys
Die Zeit nimmt stark zu, aber immer noch klein im Vergleich zum Benutzer oder echt?Ich benutze oft
cat file | myprogram
in Beispielen. Manchmal werde ich des nutzlosen Gebrauchs von Katzen beschuldigt ( http://porkmail.org/era/unix/award.html ). Ich bin aus folgenden Gründen nicht einverstanden:Es ist leicht zu verstehen, was los ist.
Beim Lesen eines UNIX-Befehls erwarten Sie einen Befehl, gefolgt von Argumenten, gefolgt von einer Umleitung. Es ist möglich, die Umleitung an einer beliebigen Stelle zu platzieren, sie wird jedoch selten angezeigt. Daher fällt es den Benutzern schwerer, das Beispiel zu lesen. Ich glaube
ist leichter zu lesen als
Wenn Sie die Umleitung an den Anfang verschieben, verwirren Sie Personen, die an diese Syntax nicht gewöhnt sind:
und Beispiele sollten leicht zu verstehen sein.
Es ist leicht zu ändern.
Wenn Sie wissen, dass das Programm lesen kann
cat
, können Sie normalerweise davon ausgehen, dass es die Ausgabe von jedem Programm lesen kann, das an STDOUT ausgegeben wird. Auf diese Weise können Sie es an Ihre eigenen Bedürfnisse anpassen und vorhersehbare Ergebnisse erzielen.Es wird betont, dass das Programm nicht fehlschlägt, wenn STDIN keine Datei ist.
Es ist nicht sicher anzunehmen, dass wenn es
program1 < foo
funktioniert,cat foo | program1
es auch funktioniert. Es ist jedoch sicher, das Gegenteil anzunehmen. Dieses Programm funktioniert, wenn STDIN eine Datei ist, schlägt jedoch fehl, wenn die Eingabe eine Pipe ist, da es seek verwendet:Leistungskosten
Die zusätzlichen Kosten fallen an
cat
. Um eine Vorstellung davon zu geben, wie oft ich einige Tests durchgeführt habe, um Baseline (cat
), niedrigen Durchsatz (bzip2
), mittleren Durchsatz (gzip
) und hohen Durchsatz (grep
) zu simulieren .Die Tests wurden auf einem Low-End-System (0,6 GHz) und einem normalen Laptop (2,2 GHz) durchgeführt. Sie wurden 10 Mal auf jedem System ausgeführt und das beste Timing wurde ausgewählt, um die optimale Situation für jeden Test nachzuahmen. Die $ ISO war ubuntu-11.04-desktop-i386.iso. (Schönere Tabellen hier: http://oletange.blogspot.com/2013/10/useless-use-of-cat.html )
Die Ergebnisse zeigen, dass bei geringem und mittlerem Durchsatz die Kosten in der Größenordnung von 1% liegen. Dies liegt innerhalb der Unsicherheit der Messungen, sodass in der Praxis kein Unterschied besteht.
Bei hohem Durchsatz ist der Unterschied größer und es gibt einen deutlichen Unterschied zwischen den beiden.
Das führt zu der Schlussfolgerung: Sie sollten
<
anstelle voncat |
if verwenden:Ansonsten spielt es keine Rolle, ob Sie
<
oder verwendencat |
.Und deshalb sollten Sie einen UUoC-Award nur dann vergeben, wenn:
quelle
Ich denke, dass (auf traditionelle Weise) die Verwendung von Rohren etwas schneller ist; auf meiner Box habe ich benutzt
strace
Befehl um zu sehen, was los ist:Ohne Rohr:
Und mit Pfeife:
Sie können einige Tests mit
strace
undtime
Befehle mit mehr und längeren Befehlen durchführen, um ein gutes Benchmarking zu erzielen.quelle
strace
, dass dies zeigt, dass es schneller ist - im zweiten Fall wirdstrace
diewc -l
Ausführung nicht verfolgt . Hier wird nur der erste Befehl der Pipeline verfolgt.strace -f sh -c 'wc -l < wrong_output.c'
daneben stehenstrace -f sh -c 'cat wrong_output.c | wc -l'
.cat
: ideone.com/2w1W42#stderrmkfifo
erstellt eine benannte Pipe. Eine anonyme Pipe wird mitpipe(2)
und dann gegabelt eingerichtet, wobei Eltern und Kind unterschiedliche Enden der Pipe schließen. Aber ja, diese Antwort ist totaler Unsinn und hat nicht einmal versucht, die Systemaufrufe zu zählen oder zu verwendenstrace -O
, um den Overhead zu messen oder-r
jeden Anruf relativ zum letzten zu zeitstempeln ...