Ich war mir der Auszeichnung bis heute nicht bewusst, als ein Anfänger versuchte, die UUOC für eine meiner Antworten an mich zu binden. Es war ein cat file.txt | grep foo | cut ... | cut ...
. Ich gab ihm einen Teil meiner Meinung und besuchte erst dann den Link, den er mir gab, um auf die Ursprünge der Auszeichnung und die Praxis hinzuweisen. Weitere Suche führte mich zu dieser Frage. Etwas unglücklicherweise enthielt trotz bewusster Überlegung keine der Antworten meine Begründung.
Ich wollte nicht defensiv sein, wenn ich ihn erziehe. Schließlich hätte ich in meinen jüngeren Jahren den Befehl so geschrieben, als grep foo file.txt | cut ... | cut ...
ob Sie bei jeder häufigen Single grep
die Platzierung des Datei-Arguments lernen und wissen, dass das erste das Muster und das spätere die Dateinamen sind.
Es war eine bewusste Entscheidung, als ich die Frage mit dem cat
Präfix beantwortete, teilweise aus Gründen des "guten Geschmacks" (in den Worten von Linus Torvalds), hauptsächlich aber aus zwingenden Gründen der Funktion.
Der letztere Grund ist wichtiger, also werde ich ihn zuerst herausbringen. 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 gespleißt wird. In diesem Fall eine Datei Argument grep vermasselt Wiederverwertbarkeit aufweisen und ganz tun vielleicht so leise , ohne eine Fehlermeldung , wenn das Dateiargument vorhanden ist . Ich e. grep foo xyz | grep bar xyz | wc
gibt an, wie viele Zeilen xyz
enthalten sind, bar
während Sie die Anzahl der Zeilen erwarten, die sowohl foo
als auch enthalten bar
. Das Ändern von Argumenten in einem Befehl in einer Pipeline vor dessen Verwendung ist fehleranfällig. Wenn Sie die Möglichkeit stiller Fehler hinzufügen, wird dies zu einer besonders heimtückischen 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 man im Moment, in dem jemand, der Bildung benötigt, sagt "aber nicht", nicht denken kann diese Katze nutzlos ".
Ich werde jedoch versuchen, auch den erwähnten früheren "guten Geschmack" bewusst zu machen. Dieser Grund hat mit dem orthogonalen Designgeist von Unix zu tun. grep
tut nicht cut
und ls
tut nicht grep
. Das widerspricht also zumindest grep foo file1 file2 file3
dem Designgeist. Die orthogonale Vorgehensweise ist cat file1 file2 file3 | grep foo
. Jetzt grep foo file1
ist es nur ein Sonderfall von grep foo file1 file2 file3
, und wenn Sie es nicht gleich behandeln, verbrauchen Sie zumindest die Gehirn-Taktzyklen, um den unnützen Katzenpreis zu vermeiden.
Das führt uns zu dem Argument, grep foo file1 file2 file3
das verkettet und cat
verkettet, so dass es angemessen ist, cat file1 file2 file3
aber weil cat
es nicht verkettet, cat file1 | grep foo
verletzen wir den Geist von sowohl dem cat
als auch dem allmächtigen Unix. Nun, wenn das der Fall wäre, würde Unix einen anderen Befehl benötigen, um die Ausgabe einer Datei zu lesen und auf stdout zu spucken (nicht paginieren oder irgendetwas anderes, nur auf stdout spucken). Sie würden also die Situation haben, in der Sie sagen cat file1 file2
oder Sie sagen dog file1
und gewissenhaft daran denken, cat file1
zu vermeiden, die Auszeichnung zu erhalten, und gleichzeitig zu vermeiden, dog file1 file2
da das Design von hoffentlich dog
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 enthalten, um eine Datei in stdout zu spucken, und gleichzeitig cat
für die Verkettung einen Namen vergeben, anstatt einen anderen Namen zu vergeben. <edit>
da ist so ein hund, der unglückliche <
betreiber. Es ist bedauerlich, dass es sich am Ende der Pipeline befindet und sich nicht leicht zusammensetzen lässt. Es gibt keine syntaktisch oder ästhetisch saubere Möglichkeit, es am Anfang zu platzieren. Es ist auch bedauerlich, nicht allgemein genug zu sein, so dass Sie mit dem Hund beginnen, aber einfach einen anderen Dateinamen hinzufügen, wenn Sie möchten, dass er auch nach dem vorherigen verarbeitet wird. (Die >
ist andererseits nicht halb so schlecht. Sie hat am Ende eine nahezu perfekte Platzierung. Sie ist normalerweise kein wiederverwendbarer Teil einer Pipeline und wird dementsprechend symbolisch unterschieden.)</edit>
Die nächste Frage ist, warum es wichtig ist, Befehle zu haben, die lediglich eine Datei ausspucken oder mehrere Dateien ohne weitere Verarbeitung zu stdout verketten. Ein Grund besteht darin, zu vermeiden, dass jeder einzelne Unix-Befehl, der auf der Standardeingabe ausgeführt wird, weiß, wie mindestens ein Befehlszeilenargument analysiert und als Eingabe verwendet wird, falls vorhanden. Der zweite Grund besteht darin, zu vermeiden, dass Benutzer sich Folgendes merken müssen: (a) wohin die Dateinamenargumente führen; 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, für Befehle, die häufig und eigenständig (und nicht als Pipeline) verwendet werden, eine flüssige Benutzerführung zu ermöglichen . 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 zuzulassen grep
. (Übrigens, das ls
hat einen ganz anderen Grund, Dateiargumente nicht nur zu akzeptieren, sondern so ziemlich zu verlangen)
Schliesslich hätte man es besser machen können, wenn solche aussergewöhnlichen Befehle grep
(aber nicht notwendigerweise ls
) einen Fehler erzeugen, wenn die Standardeingabe verfügbar ist. Dies ist sinnvoll, da die Befehle Logik enthalten, die den orthogonalen Geist des allmächtigen Unix für die Benutzerfreundlichkeit verletzt. Zur weiteren Bequemlichkeit des Benutzers, dh zur Verhinderung des durch einen stillen Fehler verursachten Leidens, sollten solche Befehle nicht zögern, ihre eigene Verletzung zu verletzen, indem sie den Benutzer benachrichtigen, wenn die Möglichkeit eines stillen Fehlers besteht.