meillo@6: Das Werkzeugkaestle, #1 meillo@0: meillo@6: cut - cut out selected fields of each line of a file meillo@6: ---------------------------------------------------- meillo@6: markus schnalke meillo@6: 2015-05 meillo@0: meillo@0: meillo@1: Cut ist ein klassisches Programm im Unix-Werkzeugkasten. meillo@0: In keinem ordentlichen Tutorial zur Shellprogrammierung darf meillo@0: es fehlen. Es ist ein schoenes Anschauungs- und Beispielobjekt meillo@4: fuer's Shellscripting. Hier will ich ein wenig hinter die meillo@4: Fassade schauen. meillo@0: meillo@0: meillo@4: Funktionsweise meillo@4: meillo@4: Die Funktionsbasis von cut waren urspruenglich zwei Modi, die meillo@4: spaeter um einen dritten erweitert wurden. Cut schneidet meillo@4: entweder bestimmte Zeichen aus den Zeilen der Eingabe oder meillo@0: bestimmte durch Trennzeichen definierte Felder. meillo@0: meillo@4: Der Zeichenmodus ist geeignet um Ausschnitte aus meillo@4: Festbreitenformaten zu extrahieren. So kann man damit meillo@4: beispielsweise bestimmte Zugriffsrechte aus der Ausgabe von meillo@4: `ls -l' ausschneiden. Hier die Rechte des Besitzers: meillo@0: meillo@4: $ ls -l foo | cut -c 2-4 meillo@4: rw- meillo@0: meillo@4: Oder die Schreibrechte des Besitzers, der Gruppe und der meillo@4: Welt: meillo@0: meillo@4: $ ls -l | cut -c 3,6,9 meillo@4: ww- meillo@0: meillo@4: Mit cut lassen sich aber auch Strings kuerzen. meillo@0: meillo@6: $ echo "$long" | cut -c -20 meillo@0: meillo@4: Dieser Befehl gibt die ersten maximal 20 Zeichen (jeder meillo@4: Zeile) von `$long' aus. meillo@0: meillo@4: Geht es aber nicht um die Darstellung von Zeichen, sondern um meillo@4: ihre Speicherung, dann ist `-c' nicht unbedingt die passende meillo@4: Option. Frueher, als US-ASCII als Zeichensatz und -kodierung meillo@4: noch omnipraesent war, wurde jedes Zeichen mit genau einem meillo@4: Byte gespeichert. Somit selektierte `cut -c' gleichermassen meillo@4: sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von meillo@4: Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von meillo@4: dieser Annahme loesen. In diesem Zug bekam cut mit meillo@4: POSIX.2-1992 die Option `-b'. Diese selektiert Bytes. Will man meillo@4: also nur die ersten maximal 500 Bytes vor dem meillo@0: Newline-Zeichen stehen haben (und den Rest stillschweigend meillo@0: ignorieren), dann macht man das mit: meillo@0: meillo@6: $ cut -b -500 meillo@0: meillo@4: Den Rest kann man sich mit `cut -b 501-' einfangen. Diese meillo@4: Funktion ist insbesondere fuer POSIX wichtig, da so sicher meillo@4: gestellt werden kann, dass Textdateien keine beliebig meillo@4: langen Zeilen haben. meillo@4: [ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17 meillo@0: meillo@0: Neben dem Zeichen- bzw. Byte-Modus bietet cut noch den meillo@0: interessanteren Feld-Modus, den man mit `-f' einleitet. Mit ihm meillo@4: koennen Felder ausgewaehlt werden. Das Trennzeichen (per meillo@4: Default der Tab) kann mit `-d' geaendert werden. meillo@0: meillo@0: Der typische Anwendungsfall fuer den Feld-Modus. Ist die meillo@0: Extraktion von Information aus der passwd-Datei. So z.B. der meillo@0: Username, die User-ID und das Homeverzeichnis: meillo@0: meillo@6: $ cut -d: -f1,3,6 /etc/passwd meillo@0: meillo@0: (Die Argumente fuer die Optionen koennen bei cut uebrigens meillo@0: direkt angehaengt oder mit Whitespace abgetrennt folgen.) meillo@0: meillo@0: meillo@4: Dieser Feld-Modus ist fuer einfache tabellarische Dateien, meillo@4: wie eben die passwd, gut geeignet. Er kommt aber schnell an meillo@0: seine Grenzen. Gerade der uebliche Fall, dass an Whitespace meillo@0: in Felder geteilt werden soll, wird damit nicht abgedeckt. meillo@0: Der Delimiter kann nur genau ein Zeichen sein. Es kann also meillo@0: nicht sowohl an Leerzeichen als auch an Tabs getrennt werden. meillo@0: Auch unterteilt cut an jedem Trennzeichen. Zwei aneinander meillo@4: stehende Trennzeichen fuehren zu einem leeren Feld. Dieses meillo@4: Verhalten widerspricht den Erwartungen fuer eine Datei mit meillo@4: Whitespace-getrennten Feldern. (Manche Implementierungen von meillo@4: cut, z.B. die von FreeBSD, haben deshalb Erweiterungen, die meillo@4: das gewuenschte Verhalten fuer Whitespace-getrennte Felder meillo@4: bieten.) Ansonsten, d.h. wenn man portabel bleiben will, meillo@4: hilft awk. meillo@0: meillo@4: Awk bietet noch eine weitere Funktion, die cut missen meillo@4: laesst: Das Tauschen der Felder-Reihenfolge. Bei cut ist die meillo@4: Reihenfolge der Feldauswahl irrelevant; ein Feld kann selbst meillo@4: mehrfach angegeben werden. Der Aufruf von `cut -c 5-8,1,4-6' meillo@4: gibt z.B. die Zeichen Nummer 1, 4, 5, 6, 7 und 8 aus. Die meillo@4: Auswahl aehnelt damit der Mengenlehre in der Mathematik: meillo@4: Jedes angegebene Feld soll in der Ergebnismenge sein. Die meillo@4: Felder der Ergebnismenge werden dabei immer in der gleichen meillo@4: Reihenfolge ausgegeben wie sie in der Eingabe waren. meillo@0: meillo@0: meillo@0: Geschichtliches meillo@0: meillo@4: Cut erblickte 1982 mit dem Release von UNIX System III das meillo@4: Licht der oeffentlichen Welt. Wenn man die Quellen von System meillo@4: III durchforstet, findet man die Quellcodedatei cut.c mit dem meillo@4: Zeitstempel 1980-04-11. meillo@1: [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd meillo@4: Das ist die aelteste Manifestation des Programms, die ich meillo@4: aufstoebern konnte. meillo@0: meillo@1: Aber werfen wir doch einen Blick auf die BSD-Linie: Dort ist mein meillo@1: fruehester Fund ein cut.c mit dem Datum 1986-11-07 im Code der meillo@6: Spezialversion 4.3BSD-UWisc, meillo@6: [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix meillo@6: die im Januar 1987 veroeffentlicht wurde. meillo@1: [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut meillo@4: Die Datei unterscheidet sich nur minimal von der aus System III. meillo@4: Im bekannteren 4.3BSD-Tahoe (1988) taucht cut aber nicht auf. meillo@4: Im darauf folgenden 4.3BSD-Reno (1990) gibt es wiederum ein meillo@4: cut ... ein von Adam S. Moskowitz und Marciano Pitargue neu meillo@4: implementiertes cut, das 1989 in BSD aufgenommen wurde. meillo@1: [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut meillo@4: Seine Manpage meillo@1: [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1 meillo@4: erwaehnt bereits die erwartete Konformitaet mit POSIX.2. meillo@4: Nun sollte man wissen, dass POSIX.2 erst im September meillo@4: 1992 veroeffentlicht wurde, gut zwei Jahren *nachdem* die meillo@4: Manpage und das Programm geschrieben wurden. Dieses cut meillo@4: wurde also anhand von Entwuerfen des Standards meillo@4: implementiert. Zweieinhalb Jahre Arbeit war immerhin schon in meillo@4: den Standardisierungsprozess geflossen; bis zur meillo@4: Fertigstellung sollte es noch weitere zwei Jahre dauern. meillo@0: meillo@1: Trotz all dieser Jahreszahlen aus den 80er Jahren gehoert cut meillo@1: aus Sicht des urspruenglichen Unix zu den juengeren Tools. meillo@1: Wenn cut auch ein Jahrzehnt aelter als Linux, der Kernel, ist, meillo@4: so war Unix doch schon ueber zehn Jahre alt, als cut das meillo@4: erste Mal auftauchte. Insbesondere gehoerte cut noch nicht meillo@4: zu Version 7 Unix, das die Ausgangsbasis aller modernen meillo@4: Unix-Systeme darstellt. Die weit komplexeren Programme sed meillo@4: und awk waren dort schon vertreten. Man muss sich also meillo@4: fragen, warum cut ueberhaupt noch entwickelt wurde, wo es meillo@4: schon zwei Programme gab, die die Aufgabe von cut bereits meillo@4: abdeckten. Ein Argument fuer cut ist seine Kompaktheit und meillo@4: die damit verbundene Geschwindigkeit gegenueber dem damals meillo@4: traegen awk. Diese schlanke Gestalt ist es auch, die der Unix meillo@4: Philosopie entspricht: Mache eine Aufgabe und die richtig! meillo@4: So bewaehrte sich cut. Es wurde in andere Unix Varianten meillo@4: uebernommen, standardisiert und ist heutzutage ueberall meillo@1: anzutreffen. meillo@1: meillo@5: Die urspruengliche Variante (ohne -b) taucht schon 1985 in meillo@5: der System V Interface Definition, einer wichtigen formalen meillo@5: Beschreibung von UNIX System V, und in allen relevanten meillo@5: Standards seither auf. Mit POSIX.2 im Jahre 1992 wurde cut meillo@5: zum ersten Mal in der heutigen Form (mit -b) standardisiert. meillo@1: meillo@1: meillo@2: Beschreibungen meillo@1: meillo@2: Interessant ist ein Vergleich der Kurzbeschreibungen von cut, meillo@3: wie sie sich in der Titelzeile von Manpages oder manchmal auch meillo@5: am Anfang der Quellcodedatei finden. meillo@2: meillo@5: Die folgende Liste ist grob nach Zeit geordnet und nach meillo@5: Abstammung gruppiert: meillo@3: meillo@3: meillo@2: System III cut out selected fields of each line of a file meillo@3: System III (src) cut and paste columns of a table (projection of a relation) meillo@2: System V cut out selected fields of each line of a file meillo@2: HP-UX cut out (extract) selected fields of each line of a file meillo@2: meillo@3: 4.3BSD-UWisc (src) cut and paste columns of a table (projection of a relation) meillo@2: 4.3BSD-Reno select portions of each line of a file meillo@2: NetBSD select portions of each line of a file meillo@2: FreeBSD 1.0 select portions of each line of a file meillo@3: FreeBSD 7.0 cut out selected portions of each line of a file meillo@2: SunOS 4.1.3 remove selected fields from each line of a file meillo@2: SunOS 5.5.1 cut out selected fields of each line of a file meillo@2: meillo@2: POSIX cut out selected fields of each line of a file meillo@2: meillo@2: GNU coreutils remove sections from each line of files meillo@2: meillo@2: Minix select out columns of a file meillo@2: meillo@2: Version 8 Unix rearrange columns of data meillo@2: ``Unix Reader'' rearrange columns of text meillo@2: meillo@2: meillo@5: Die zwei mit ``(src)'' markierten Beschreibungen sind aus meillo@5: dem Quellcode entnommen, und verdeutlichen den Codetransfer. meillo@5: POSIX ist ein Set von Standards, keine Implementierung. Der meillo@5: ``Unix Reader'' ist ein rueckblickendes Textdokument von meillo@5: Doug McIlroy, das das Auftreten von Tools in der Geschichte meillo@5: des Research Unix zum Thema hat. Alle uebrigen Beschreibungen meillo@5: entstammen den Manpages. meillo@5: meillo@5: Zumeist ist mit der Zeit die POSIX-Beschreibung uebernommen meillo@5: worden, wie beispielsweise bei FreeBSD zu sehen. meillo@5: [ https://svnweb.freebsd.org/base?view=revision&revision=167101 meillo@5: meillo@5: Interessant ist, dass die GNU coreutils unveraendert vom meillo@5: Entfernen von Teilen der Eingabe sprechen, wohingegen die meillo@5: Kommandozeilenangabe klar ein Auswaehlen darstellt. Die meillo@5: Worte ``cut out'' sind vielleicht auch nicht klar genug. meillo@5: HP-UX hat sie deshalb praezisiert. meillo@5: meillo@5: Auch beim Begriff, was denn nun selektiert wird, ist man sich meillo@5: uneins. Die einen reden von Feldern (POSIX), andere von meillo@5: Abschnitten bzw. Teilen (BSD) und wieder andere von Spalten meillo@5: (Research Unix). Ironischerweise leistet sich gerade Version meillo@5: 8 Unix, das eigentlich um eine sehr treffende Weltsicht meillo@5: bemueht ist, mit ``rearrange columns of data'' die meillo@5: unzutreffendste der Beschreibungen. meillo@5: meillo@5: meillo@2: meillo@3: Codevergleich meillo@2: meillo@2: meillo@2: meillo@5: meillo@6: B-) wc -lc cut.c* | sort -n meillo@6: 123 2966 cut.c__system_iii.1980-04-11 meillo@6: 125 3038 cut.c__4.3bsd-uwisc.1986-11-07 meillo@6: 256 5715 cut.c__4.3bsd-reno.1990-06-25 meillo@6: 270 6545 cut.c__netbsd.1993-03-21 meillo@6: 296 6920 cut.c__freebsd.1994-05-27 meillo@6: 306 7500 cut.c__netbsd.2014-02-03 * meillo@6: 479 10961 cut.c__freebsd.2012-11-24 * meillo@6: 586 14175 cut.c__gnu.1992-11-08 * meillo@6: 830 23167 cut.c__gnu.2015-05-01 * meillo@6: 3271 80987 total meillo@6: meillo@6: B-) c_count cut.c* | sort -n meillo@6: Total: meillo@6: 116 cut.c__system_iii.1980-04-11 meillo@6: 118 cut.c__4.3bsd-uwisc.1986-11-07 meillo@6: 200 cut.c__4.3bsd-reno.1990-06-25 meillo@6: 200 cut.c__netbsd.1993-03-21 meillo@6: 224 cut.c__freebsd.1994-05-27 meillo@6: 232 cut.c__netbsd.2014-02-03 * meillo@6: 382 cut.c__gnu.1992-11-08 * meillo@6: 391 cut.c__freebsd.2012-11-24 * meillo@6: 588 cut.c__gnu.2015-05-01 * meillo@6: 2451 meillo@6: meillo@6: (* == version hat -b) meillo@6: meillo@6: meillo@5: meillo@5: meillo@5: cut(1) in Version 8 Unix meillo@5: ``In data base parlance, it projects a relation.'' meillo@6: meillo@6: meillo@6: meillo@6: Autoreninfo meillo@6: meillo@6: Markus Schnalke interessiert sich fuer die Hintergruende meillo@6: von Unix und seinen Werkzeugen. Fuer die Erarbeitung dieses meillo@6: Textes wurde er regelrecht zum Historiker. meillo@6: meillo@6: meillo@6: Lizenz meillo@6: CC0 (und kann damit auch unter CC BY-SA 4.0 Unported meillo@6: veroeffentlicht werden)