Mercurial > docs > cut
view cut.txt @ 6:bf2ac5df0063
Zwischenstand
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sun, 03 May 2015 18:08:00 +0200 |
parents | 00097c80a853 |
children | 21ca59543b07 |
line wrap: on
line source
Das Werkzeugkaestle, #1 cut - cut out selected fields of each line of a file ---------------------------------------------------- markus schnalke <meillo@marmaro.de> 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 will ich ein wenig hinter die Fassade schauen. 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 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 rw- Oder die Schreibrechte des Besitzers, der Gruppe und der Welt: $ ls -l | cut -c 3,6,9 ww- Mit cut lassen sich aber auch Strings kuerzen. $ echo "$long" | cut -c -20 Dieser Befehl gibt die ersten maximal 20 Zeichen (jeder Zeile) von `$long' aus. 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 -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. Der typische Anwendungsfall fuer den Feld-Modus. Ist die Extraktion von Information aus der passwd-Datei. So z.B. der Username, die User-ID und das Homeverzeichnis: $ cut -d: -f1,3,6 /etc/passwd (Die Argumente fuer die Optionen koennen bei cut uebrigens direkt angehaengt oder mit Whitespace abgetrennt folgen.) 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. 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 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 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, [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix die im Januar 1987 veroeffentlicht wurde. [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut 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 Seine Manpage [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1 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 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. Die urspruengliche Variante (ohne -b) taucht schon 1985 in der System V Interface Definition, einer wichtigen formalen Beschreibung von UNIX System V, und in allen relevanten Standards seither auf. Mit POSIX.2 im Jahre 1992 wurde cut zum ersten Mal in der heutigen Form (mit -b) standardisiert. Beschreibungen Interessant ist ein Vergleich der Kurzbeschreibungen von cut, wie sie sich in der Titelzeile von Manpages oder manchmal auch am Anfang der Quellcodedatei finden. Die folgende Liste ist grob nach Zeit geordnet und nach Abstammung gruppiert: System III cut out selected fields of each line of a file System III (src) cut and paste columns of a table (projection of a relation) System V cut out selected fields of each line of a file HP-UX cut out (extract) selected fields of each line of a file 4.3BSD-UWisc (src) cut and paste columns of a table (projection of a relation) 4.3BSD-Reno select portions of each line of a file NetBSD select portions of each line of a file FreeBSD 1.0 select portions of each line of a file FreeBSD 7.0 cut out selected portions of each line of a file SunOS 4.1.3 remove selected fields from each line of a file SunOS 5.5.1 cut out selected fields of each line of a file POSIX cut out selected fields of each line of a file GNU coreutils remove sections from each line of files Minix select out columns of a file Version 8 Unix rearrange columns of data ``Unix Reader'' rearrange columns of text Die zwei mit ``(src)'' markierten Beschreibungen sind aus dem Quellcode entnommen, und verdeutlichen den Codetransfer. POSIX ist ein Set von Standards, keine Implementierung. Der ``Unix Reader'' ist ein rueckblickendes Textdokument von Doug McIlroy, das das Auftreten von Tools in der Geschichte des Research Unix zum Thema hat. Alle uebrigen Beschreibungen entstammen den Manpages. Zumeist ist mit der Zeit die POSIX-Beschreibung uebernommen worden, wie beispielsweise bei FreeBSD zu sehen. [ https://svnweb.freebsd.org/base?view=revision&revision=167101 Interessant ist, dass die GNU coreutils unveraendert vom Entfernen von Teilen der Eingabe sprechen, wohingegen die Kommandozeilenangabe klar ein Auswaehlen darstellt. Die Worte ``cut out'' sind vielleicht auch nicht klar genug. HP-UX hat sie deshalb praezisiert. Auch beim Begriff, was denn nun selektiert wird, ist man sich uneins. Die einen reden von Feldern (POSIX), andere von Abschnitten bzw. Teilen (BSD) und wieder andere von Spalten (Research Unix). Ironischerweise leistet sich gerade Version 8 Unix, das eigentlich um eine sehr treffende Weltsicht bemueht ist, mit ``rearrange columns of data'' die unzutreffendste der Beschreibungen. Codevergleich B-) wc -lc cut.c* | sort -n 123 2966 cut.c__system_iii.1980-04-11 125 3038 cut.c__4.3bsd-uwisc.1986-11-07 256 5715 cut.c__4.3bsd-reno.1990-06-25 270 6545 cut.c__netbsd.1993-03-21 296 6920 cut.c__freebsd.1994-05-27 306 7500 cut.c__netbsd.2014-02-03 * 479 10961 cut.c__freebsd.2012-11-24 * 586 14175 cut.c__gnu.1992-11-08 * 830 23167 cut.c__gnu.2015-05-01 * 3271 80987 total B-) c_count cut.c* | sort -n Total: 116 cut.c__system_iii.1980-04-11 118 cut.c__4.3bsd-uwisc.1986-11-07 200 cut.c__4.3bsd-reno.1990-06-25 200 cut.c__netbsd.1993-03-21 224 cut.c__freebsd.1994-05-27 232 cut.c__netbsd.2014-02-03 * 382 cut.c__gnu.1992-11-08 * 391 cut.c__freebsd.2012-11-24 * 588 cut.c__gnu.2015-05-01 * 2451 (* == version hat -b) cut(1) in Version 8 Unix ``In data base parlance, it projects a relation.'' Autoreninfo Markus Schnalke interessiert sich fuer die Hintergruende von Unix und seinen Werkzeugen. Fuer die Erarbeitung dieses Textes wurde er regelrecht zum Historiker. Lizenz CC0 (und kann damit auch unter CC BY-SA 4.0 Unported veroeffentlicht werden)