# HG changeset patch # User markus schnalke # Date 1430599740 -7200 # Node ID d0b61c2bd25cdd576e60687636089ff2ec35b7ea # Parent 7cd149433a967c83da11a6e681a2da3fd41bec84 Zwischenstand diff -r 7cd149433a96 -r d0b61c2bd25c cut.txt --- a/cut.txt Sat May 02 18:47:00 2015 +0200 +++ b/cut.txt Sat May 02 22:49:00 2015 +0200 @@ -2,70 +2,69 @@ #1: cut - cut out selected fields of each line of a file --------------------------------------------------------- -markus schnalke, 2015-04 +markus schnalke, 2015-05 Cut ist ein klassisches Programm im Unix-Werkzeugkasten. In keinem ordentlichen Tutorial zur Shellprogrammierung darf es fehlen. Es ist ein schoenes Anschauungs- und Beispielobjekt -fuer's Shellscripting. Hier soll es portraitiert werden. +fuer's Shellscripting. Hier will ich ein wenig hinter die +Fassade schauen. -Die Funktionsbasis von cut sind urspruenglich zwei Modi, die -spaeter um einen dritten erweitert wurden. Entweder cut -schneidet bestimmte Zeichen aus den Zeilen der Eingabe oder +Funktionsweise + +Die Funktionsbasis von cut waren urspruenglich zwei Modi, die +spaeter um einen dritten erweitert wurden. Cut schneidet +entweder bestimmte Zeichen aus den Zeilen der Eingabe oder bestimmte durch Trennzeichen definierte Felder. -Der Zeichenmodus ist besonders praktisch um bestimmte Teile -von Kommandoausgaben zu extrahieren. Ein populaeres -Beispiel ist die Jahreszahl, die aus einer Datumsangabe -herausgeschnitten werden soll, insofern das Datumsformat -nicht frei gewaehlt werden kann. Ein anderer Anwendungsfall -ist die Extraktion bestimmter Zugriffsrecht. Hier z.B. die -Rechte fuer den Besitzer: +Der Zeichenmodus ist geeignet um Ausschnitte aus +Festbreitenformaten zu extrahieren. So kann man damit +beispielsweise bestimmte Zugriffsrechte aus der Ausgabe von +`ls -l' ausschneiden. Hier die Rechte des Besitzers: - ls -l foo | cut -c 2-4 + $ ls -l foo | cut -c 2-4 + rw- -Oder die Schreibrechte fuer die Gruppe und alle anderen: +Oder die Schreibrechte des Besitzers, der Gruppe und der +Welt: - ls -l | cut -c 6,9 + $ ls -l | cut -c 3,6,9 + ww- -Damit ist die grundsaetzliche Verwendung von cut -demonstriert. +Mit cut lassen sich aber auch Strings kuerzen. -Die fuer POSIX wichtige Funktion von cut ist die Faehigkeit -lange Zeilen zu kuerzen. + echo "$long" | cut -c -20 - cut -c -80 +Dieser Befehl gibt die ersten maximal 20 Zeichen (jeder +Zeile) von `$long' aus. -Dieser Befehl uebernimmt nur die ersten 80 Zeichen der -Eingabe in die Ausgabe. Der Rest der Zeilen wird einfach -abgeschnitten, koennte aber mit `cut -c 81-' extrahiert -werden. - -Achtzig Zeichen erinnert unweigerlich an VT100-Terminals, -das 80 Zeichen pro Zeile darstellen kann. Geht es aber nicht -um die Darstellung von Zeichen sondern um ihre Speicherung, -dann ist `-c' nicht unbedingt die passende Option zur Kuerzung -langer Zeilen. - -Frueher, als US-ASCII omnipraesente als Zeichensatz und -kodierung -war, war jedes Zeichen durch genau ein Byte kodiert und somit -selektierte `cut -c' sowohl nach Ausgabezeichen als auch nach -Bytes. Mit dem Aufkommen von Multibyte-Kodierungen (wie UTF-8) -musste man sich von dieser Annahme loesen. In diesem Zug -bekam cut mit POSIX.2-1992 die Option `-b'. Diese selektiert -Bytes. Will man also nur die ersten maximal 20 Bytes vor dem +Geht es aber nicht um die Darstellung von Zeichen, sondern um +ihre Speicherung, dann ist `-c' nicht unbedingt die passende +Option. Frueher, als US-ASCII als Zeichensatz und -kodierung +noch omnipraesent war, wurde jedes Zeichen mit genau einem +Byte gespeichert. Somit selektierte `cut -c' gleichermassen +sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von +Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von +dieser Annahme loesen. In diesem Zug bekam cut mit +POSIX.2-1992 die Option `-b'. Diese selektiert Bytes. Will man +also nur die ersten maximal 500 Bytes vor dem Newline-Zeichen stehen haben (und den Rest stillschweigend ignorieren), dann macht man das mit: - cut -b -20 + cut -b -500 +Den Rest kann man sich mit `cut -b 501-' einfangen. Diese +Funktion ist insbesondere fuer POSIX wichtig, da so sicher +gestellt werden kann, dass Textdateien keine beliebig +langen Zeilen haben. +[ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17 Neben dem Zeichen- bzw. Byte-Modus bietet cut noch den interessanteren Feld-Modus, den man mit `-f' einleitet. Mit ihm -koennen Felder ausgewaehlt werden. Das Trennzeichen -- per -Default der Tab -- kann mit `-d' geaendert werden. +koennen Felder ausgewaehlt werden. Das Trennzeichen (per +Default der Tab) kann mit `-d' geaendert werden. Der typische Anwendungsfall fuer den Feld-Modus. Ist die Extraktion von Information aus der passwd-Datei. So z.B. der @@ -77,61 +76,80 @@ direkt angehaengt oder mit Whitespace abgetrennt folgen.) -Dieser Feld-Modus ist fuer einfache tabellarische Dateien -(wie eben die passwd) gut geeignet, kommt aber schnell an +Dieser Feld-Modus ist fuer einfache tabellarische Dateien, +wie eben die passwd, gut geeignet. Er kommt aber schnell an seine Grenzen. Gerade der uebliche Fall, dass an Whitespace in Felder geteilt werden soll, wird damit nicht abgedeckt. Der Delimiter kann nur genau ein Zeichen sein. Es kann also nicht sowohl an Leerzeichen als auch an Tabs getrennt werden. Auch unterteilt cut an jedem Trennzeichen. Zwei aneinander -stehende Trennzeichen fuehren zu einem leeren Feld. Solches -Verhalten ist fuer Whitespace-getrennte Felder unangemessen. -Diese Aufgaben deckt aber zum Glueck awk ab, so dass die -Alternative zur Hand ist. +stehende Trennzeichen fuehren zu einem leeren Feld. Dieses +Verhalten widerspricht den Erwartungen fuer eine Datei mit +Whitespace-getrennten Feldern. (Manche Implementierungen von +cut, z.B. die von FreeBSD, haben deshalb Erweiterungen, die +das gewuenschte Verhalten fuer Whitespace-getrennte Felder +bieten.) Ansonsten, d.h. wenn man portabel bleiben will, +hilft awk. -Awk hat eine weitere Funktion, die -cut missen laesst: Das Tauschen der Feld-Reihenfolge. - - - +Awk bietet noch eine weitere Funktion, die cut missen +laesst: Das Tauschen der Felder-Reihenfolge. Bei cut ist die +Reihenfolge der Feldauswahl irrelevant; ein Feld kann selbst +mehrfach angegeben werden. Der Aufruf von `cut -c 5-8,1,4-6' +gibt z.B. die Zeichen Nummer 1, 4, 5, 6, 7 und 8 aus. Die +Auswahl aehnelt damit der Mengenlehre in der Mathematik: +Jedes angegebene Feld soll in der Ergebnismenge sein. Die +Felder der Ergebnismenge werden dabei immer in der gleichen +Reihenfolge ausgegeben wie sie in der Eingabe waren. Geschichtliches -Cut erblickte 1982 als Teil von UNIX System III das Licht der -oeffentlichen Welt. In den Quellen von System III findet sich -cut.c mit dem Zeitstempel 1980-04-11. +Cut erblickte 1982 mit dem Release von UNIX System III das +Licht der oeffentlichen Welt. Wenn man die Quellen von System +III durchforstet, findet man die Quellcodedatei cut.c mit dem +Zeitstempel 1980-04-11. [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd +Das ist die aelteste Manifestation des Programms, die ich +aufstoebern konnte. Aber werfen wir doch einen Blick auf die BSD-Linie: Dort ist mein fruehester Fund ein cut.c mit dem Datum 1986-11-07 im Code der Spezialversion 4.3BSD-UWisc, die im Januar 1987 veroeffentlicht -. +wurde. [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut -Im bekannteren 4.3BSD-Tahoe (1988) taucht es nicht auf. Im -darauf folgenden 4.3BSD-Reno (1990) gibt es aber wiederum ein -cut, das von Adam S. Moskowitz und Marciano Pitargue geschrieben -und 1989 in BSD aufgenommen worden ist. +Die Datei unterscheidet sich nur minimal von der aus System III. +Im bekannteren 4.3BSD-Tahoe (1988) taucht cut aber nicht auf. +Im darauf folgenden 4.3BSD-Reno (1990) gibt es wiederum ein +cut ... ein von Adam S. Moskowitz und Marciano Pitargue neu +implementiertes cut, das 1989 in BSD aufgenommen wurde. [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut -Die Manpage +Seine Manpage [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1 -erwaehnt bereits die angestrebte aber noch vermutete Konformitaet -zu POSIX.2. Man muss wissen, dass POSIX.2 erst im September -1992 veroeffentlicht wurde. Die Aussage basiert also auf dem -Zwischenstand nach zweieinhalb der insgesamt fuenf Jahre, die -die Arbeiten am Standard benoetigten. +erwaehnt bereits die erwartete Konformitaet mit POSIX.2. +Nun sollte man wissen, dass POSIX.2 erst im September +1992 veroeffentlicht wurde, gut zwei Jahren *nachdem* die +Manpage und das Programm geschrieben wurden. Dieses cut +wurde also anhand von Entwuerfen des Standards +implementiert. Zweieinhalb Jahre Arbeit war immerhin schon in +den Standardisierungsprozess geflossen; bis zur +Fertigstellung sollte es noch weitere zwei Jahre dauern. Trotz all dieser Jahreszahlen aus den 80er Jahren gehoert cut aus Sicht des urspruenglichen Unix zu den juengeren Tools. Wenn cut auch ein Jahrzehnt aelter als Linux, der Kernel, ist, -so existierte Unix wiederum schon ein ganzes Jahrzehnt bevor cut -das erste Mal auftauchte. Insbesondere war cut nicht in Version 7 -Unix vorhanden, das die Ausgangsbasis aller modernen Unix-Systeme -darstellt. (Das weit komplexere sed z.B. war dort schon -vertreten.) - -Nichts desto trotz bewaehrte sich cut. Es wurde in andere -Unix Varianten uebernommen und ist heutzutage ueberall +so war Unix doch schon ueber zehn Jahre alt, als cut das +erste Mal auftauchte. Insbesondere gehoerte cut noch nicht +zu Version 7 Unix, das die Ausgangsbasis aller modernen +Unix-Systeme darstellt. Die weit komplexeren Programme sed +und awk waren dort schon vertreten. Man muss sich also +fragen, warum cut ueberhaupt noch entwickelt wurde, wo es +schon zwei Programme gab, die die Aufgabe von cut bereits +abdeckten. Ein Argument fuer cut ist seine Kompaktheit und +die damit verbundene Geschwindigkeit gegenueber dem damals +traegen awk. Diese schlanke Gestalt ist es auch, die der Unix +Philosopie entspricht: Mache eine Aufgabe und die richtig! +So bewaehrte sich cut. Es wurde in andere Unix Varianten +uebernommen, standardisiert und ist heutzutage ueberall anzutreffen. Mit POSIX.2 im Jahre 1992 wurde cut zum ersten Mal in der