docs/cut

view cut.txt @ 7:21ca59543b07

Zwischenstand
author markus schnalke <meillo@marmaro.de>
date Sun, 03 May 2015 21:05:00 +0200
parents bf2ac5df0063
children 1dc4a9dca829
line source
1 Das Werkzeugkaestle, #1
3 cut - cut out selected fields of each line of a file
4 ----------------------------------------------------
5 markus schnalke <meillo@marmaro.de>
6 2015-05
9 Cut ist ein klassisches Programm im Unix-Werkzeugkasten.
10 In keinem ordentlichen Tutorial zur Shellprogrammierung darf
11 es fehlen. Es ist ein schoenes Anschauungs- und Beispielobjekt
12 fuer's Shellscripting. Hier will ich ein wenig hinter die
13 Fassade schauen.
16 Funktionsweise
18 Die Funktionsbasis von cut waren urspruenglich zwei Modi, die
19 spaeter um einen dritten erweitert wurden. Cut schneidet
20 entweder bestimmte Zeichen aus den Zeilen der Eingabe oder
21 bestimmte durch Trennzeichen definierte Felder.
23 Der Zeichenmodus ist geeignet um Ausschnitte aus
24 Festbreitenformaten zu extrahieren. So kann man damit
25 beispielsweise bestimmte Zugriffsrechte aus der Ausgabe von
26 `ls -l' ausschneiden. Hier die Rechte des Besitzers:
28 $ ls -l foo | cut -c 2-4
29 rw-
31 Oder die Schreibrechte des Besitzers, der Gruppe und der
32 Welt:
34 $ ls -l | cut -c 3,6,9
35 ww-
37 Mit cut lassen sich aber auch Strings kuerzen.
39 $ echo "$long" | cut -c -20
41 Dieser Befehl gibt die ersten maximal 20 Zeichen (jeder
42 Zeile) von `$long' aus.
44 Geht es aber nicht um die Darstellung von Zeichen, sondern um
45 ihre Speicherung, dann ist `-c' nicht unbedingt die passende
46 Option. Frueher, als US-ASCII als Zeichensatz und -kodierung
47 noch omnipraesent war, wurde jedes Zeichen mit genau einem
48 Byte gespeichert. Somit selektierte `cut -c' gleichermassen
49 sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von
50 Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von
51 dieser Annahme loesen. In diesem Zug bekam cut mit
52 POSIX.2-1992 die Option `-b'. Diese selektiert Bytes. Will man
53 also nur die ersten maximal 500 Bytes vor dem
54 Newline-Zeichen stehen haben (und den Rest stillschweigend
55 ignorieren), dann macht man das mit:
57 $ cut -b -500
59 Den Rest kann man sich mit `cut -b 501-' einfangen. Diese
60 Funktion ist insbesondere fuer POSIX wichtig, da so sicher
61 gestellt werden kann, dass Textdateien keine beliebig
62 langen Zeilen haben.
63 [ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17
65 Neben dem Zeichen- bzw. Byte-Modus bietet cut noch den
66 interessanteren Feld-Modus, den man mit `-f' einleitet. Mit ihm
67 koennen Felder ausgewaehlt werden. Das Trennzeichen (per
68 Default der Tab) kann mit `-d' geaendert werden.
70 Der typische Anwendungsfall fuer den Feld-Modus. Ist die
71 Extraktion von Information aus der passwd-Datei. So z.B. der
72 Username, die User-ID und das Homeverzeichnis:
74 $ cut -d: -f1,3,6 /etc/passwd
76 (Die Argumente fuer die Optionen koennen bei cut uebrigens
77 direkt angehaengt oder mit Whitespace abgetrennt folgen.)
80 Dieser Feld-Modus ist fuer einfache tabellarische Dateien,
81 wie eben die passwd, gut geeignet. Er kommt aber schnell an
82 seine Grenzen. Gerade der uebliche Fall, dass an Whitespace
83 in Felder geteilt werden soll, wird damit nicht abgedeckt.
84 Der Delimiter kann nur genau ein Zeichen sein. Es kann also
85 nicht sowohl an Leerzeichen als auch an Tabs getrennt werden.
86 Auch unterteilt cut an jedem Trennzeichen. Zwei aneinander
87 stehende Trennzeichen fuehren zu einem leeren Feld. Dieses
88 Verhalten widerspricht den Erwartungen fuer eine Datei mit
89 Whitespace-getrennten Feldern. (Manche Implementierungen von
90 cut, z.B. die von FreeBSD, haben deshalb Erweiterungen, die
91 das gewuenschte Verhalten fuer Whitespace-getrennte Felder
92 bieten.) Ansonsten, d.h. wenn man portabel bleiben will,
93 hilft awk.
95 Awk bietet noch eine weitere Funktion, die cut missen
96 laesst: Das Tauschen der Felder-Reihenfolge. Bei cut ist die
97 Reihenfolge der Feldauswahl irrelevant; ein Feld kann selbst
98 mehrfach angegeben werden. Der Aufruf von `cut -c 5-8,1,4-6'
99 gibt z.B. die Zeichen Nummer 1, 4, 5, 6, 7 und 8 aus. Die
100 Auswahl aehnelt damit der Mengenlehre in der Mathematik:
101 Jedes angegebene Feld soll in der Ergebnismenge sein. Die
102 Felder der Ergebnismenge werden dabei immer in der gleichen
103 Reihenfolge ausgegeben wie sie in der Eingabe waren.
107 cut(1) in Version 8 Unix
108 ``In data base parlance, it projects a relation.''
110 WP:
111 http://de.wikipedia.org/wiki/Projektion_(Informatik)#Projektion
113 Die Projektion entspricht der Projektionsabbildung aus der
114 Mengenlehre und kann auch Attributbeschränkung genannt
115 werden. Sie extrahiert einzelne Attribute aus der
116 ursprünglichen Attributmenge und ist somit als eine Art
117 Selektion auf Spaltenebene zu verstehen, das heißt, die
118 Projektion blendet Spalten aus.
123 Geschichtliches
125 Cut erblickte 1982 mit dem Release von UNIX System III das
126 Licht der oeffentlichen Welt. Wenn man die Quellen von System
127 III durchforstet, findet man die Quellcodedatei cut.c mit dem
128 Zeitstempel 1980-04-11.
129 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd
130 Das ist die aelteste Manifestation des Programms, die ich
131 aufstoebern konnte.
133 Aber werfen wir doch einen Blick auf die BSD-Linie: Dort ist mein
134 fruehester Fund ein cut.c mit dem Datum 1986-11-07 im Code der
135 Spezialversion 4.3BSD-UWisc,
136 [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix
137 die im Januar 1987 veroeffentlicht wurde.
138 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut
139 Die Datei unterscheidet sich nur minimal von der aus System III.
140 Im bekannteren 4.3BSD-Tahoe (1988) taucht cut aber nicht auf.
141 Im darauf folgenden 4.3BSD-Reno (1990) gibt es wiederum ein
142 cut ... ein von Adam S. Moskowitz und Marciano Pitargue neu
143 implementiertes cut, das 1989 in BSD aufgenommen wurde.
144 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut
145 Seine Manpage
146 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1
147 erwaehnt bereits die erwartete Konformitaet mit POSIX.2.
148 Nun sollte man wissen, dass POSIX.2 erst im September
149 1992 veroeffentlicht wurde, gut zwei Jahren *nachdem* die
150 Manpage und das Programm geschrieben wurden. Dieses cut
151 wurde also anhand von Entwuerfen des Standards
152 implementiert. Zweieinhalb Jahre Arbeit war immerhin schon in
153 den Standardisierungsprozess geflossen; bis zur
154 Fertigstellung sollte es noch weitere zwei Jahre dauern.
156 Trotz all dieser Jahreszahlen aus den 80er Jahren gehoert cut
157 aus Sicht des urspruenglichen Unix zu den juengeren Tools.
158 Wenn cut auch ein Jahrzehnt aelter als Linux, der Kernel, ist,
159 so war Unix doch schon ueber zehn Jahre alt, als cut das
160 erste Mal auftauchte. Insbesondere gehoerte cut noch nicht
161 zu Version 7 Unix, das die Ausgangsbasis aller modernen
162 Unix-Systeme darstellt. Die weit komplexeren Programme sed
163 und awk waren dort schon vertreten. Man muss sich also
164 fragen, warum cut ueberhaupt noch entwickelt wurde, wo es
165 schon zwei Programme gab, die die Aufgabe von cut bereits
166 abdeckten. Ein Argument fuer cut ist seine Kompaktheit und
167 die damit verbundene Geschwindigkeit gegenueber dem damals
168 traegen awk. Diese schlanke Gestalt ist es auch, die der Unix
169 Philosopie entspricht: Mache eine Aufgabe und die richtig!
170 So bewaehrte sich cut. Es wurde in andere Unix Varianten
171 uebernommen, standardisiert und ist heutzutage ueberall
172 anzutreffen.
174 Die urspruengliche Variante (ohne -b) taucht schon 1985 in
175 der System V Interface Definition, einer wichtigen formalen
176 Beschreibung von UNIX System V, und in allen relevanten
177 Standards seither auf. Mit POSIX.2 im Jahre 1992 wurde cut
178 zum ersten Mal in der heutigen Form (mit -b) standardisiert.
181 Beschreibungen
183 Interessant ist ein Vergleich der Kurzbeschreibungen von cut,
184 wie sie sich in der Titelzeile von Manpages oder manchmal auch
185 am Anfang der Quellcodedatei finden.
187 Die folgende Liste ist grob nach Zeit geordnet und nach
188 Abstammung gruppiert:
191 System III cut out selected fields of each line of a file
192 System III (src) cut and paste columns of a table (projection of a relation)
193 System V cut out selected fields of each line of a file
194 HP-UX cut out (extract) selected fields of each line of a file
196 4.3BSD-UWisc (src) cut and paste columns of a table (projection of a relation)
197 4.3BSD-Reno select portions of each line of a file
198 NetBSD select portions of each line of a file
199 OpenBSD 4.6 select portions of each line of a file
200 FreeBSD 1.0 select portions of each line of a file
201 FreeBSD 7.0 cut out selected portions of each line of a file
202 SunOS 4.1.3 remove selected fields from each line of a file
203 SunOS 5.5.1 cut out selected fields of each line of a file
205 POSIX cut out selected fields of each line of a file
207 GNU coreutils remove sections from each line of files
209 Minix select out columns of a file
211 Version 8 Unix rearrange columns of data
212 ``Unix Reader'' rearrange columns of text
215 Die zwei mit ``(src)'' markierten Beschreibungen sind aus
216 dem Quellcode entnommen, und verdeutlichen den Codetransfer.
217 POSIX ist ein Set von Standards, keine Implementierung. Der
218 ``Unix Reader'' ist ein rueckblickendes Textdokument von
219 Doug McIlroy, das das Auftreten von Tools in der Geschichte
220 des Research Unix zum Thema hat. Alle uebrigen Beschreibungen
221 entstammen den Manpages.
223 Zumeist ist mit der Zeit die POSIX-Beschreibung uebernommen
224 worden, wie beispielsweise bei FreeBSD zu sehen.
225 [ https://svnweb.freebsd.org/base?view=revision&revision=167101
227 Interessant ist, dass die GNU coreutils seit Anbeginn vom
228 Entfernen von Teilen der Eingabe sprechen, wohingegen die
229 Kommandozeilenangabe klar ein Auswaehlen darstellt. Die
230 Worte ``cut out'' sind vielleicht auch nicht klar genug.
231 HP-UX hat sie deshalb praezisiert.
233 Auch beim Begriff, was denn nun selektiert wird, ist man sich
234 uneins. Die einen reden von Feldern (POSIX), andere von
235 Abschnitten bzw. Teilen (BSD) und wieder andere von Spalten
236 (Research Unix). Ironischerweise leistet sich gerade Version
237 8 Unix, das eigentlich um eine sehr treffende Weltsicht
238 bemueht ist, mit ``rearrange columns of data'' die
239 unzutreffendste der Beschreibungen.
243 Codevergleich
245 Nun zum Blick auf den Code. Hier soll eine Auswahl an
246 Implementierungen etwas genauer betrachtet werden. Fuer einen
247 ersten Eindruck ist der Umfang des Quellcodes hilfreich.
248 Typischerweise steigt dieser ueber die Jahre an. Diese
249 Beobachtung kann hier in der Tendenz aber nicht in jedem Fall
250 bestaetigt werden. Die Unterstuetzung des Byte-Modus (-b)
251 erfordert zwangslaeufig mehr Code, deshalb ist zu erwarten,
252 dass
254 -b pseudo: openbsd, netbsd.2014, gnu*
255 -b real: freebsd.2014
257 :-& echo '123ä56' | cut -c -6 | od -c
258 0000000 1 2 3 303 244 5 \n
259 0000007
261 :-& echo '123ä56' | cut -b -6 | od -c
262 0000000 1 2 3 303 244 5 \n
263 0000007
266 $ wc -lc cut.c* | sort -n
267 123 2966 cut.c__system_iii.1980-04-11
268 125 3038 cut.c__4.3bsd-uwisc.1986-11-07
269 256 5715 cut.c__4.3bsd-reno.1990-06-25
270 270 6545 cut.c__netbsd.1993-03-21
271 290 6892 cut.c__openbsd.2008-06-27 *
272 296 6920 cut.c__freebsd.1994-05-27
273 306 7500 cut.c__netbsd.2014-02-03 *
274 479 10961 cut.c__freebsd.2012-11-24 *
275 586 14175 cut.c__gnu.1992-11-08 *
276 830 23167 cut.c__gnu.2015-05-01 *
277 3271 80987 total
279 $ c_count cut.c* | sort -n
280 Total:
281 116 cut.c__system_iii.1980-04-11
282 118 cut.c__4.3bsd-uwisc.1986-11-07
283 200 cut.c__4.3bsd-reno.1990-06-25
284 200 cut.c__netbsd.1993-03-21
285 218 cut.c__openbsd.2008-06-27 *
286 224 cut.c__freebsd.1994-05-27
287 232 cut.c__netbsd.2014-02-03 *
288 382 cut.c__gnu.1992-11-08 *
289 391 cut.c__freebsd.2012-11-24 *
290 588 cut.c__gnu.2015-05-01 *
291 2451
293 (* == version hat -b)
297 system_iii.1980-04-11 Release 1.5
299 SCCSIDs:
301 4.3bsd-uwisc.1986-11-07 "@(#)cut.c 1.3";
302 4.3bsd-reno.1990-06-25 "@(#)cut.c 5.3 (Berkeley) 6/24/90";
303 netbsd.1993-03-21 "@(#)cut.c 5.4 (Berkeley) 10/30/90";
304 freebsd.1994-05-27 "@(#)cut.c 8.1 (Berkeley) 6/6/93";
306 freebsd.2012-11-24 "@(#)cut.c 8.3 (Berkeley) 5/4/95";
307 netbsd.2014-02-03 "@(#)cut.c 8.3 (Berkeley) 5/4/95";
309 openbsd.2008-06-27 "@(#)cut.c 8.3 (Berkeley) 5/4/95";
310 "$OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $";
312 GNU
313 Copyright (C) 1997-2015 Free Software Foundation, Inc.
314 Copyright (C) 1984 David M. Ihnat
315 /* Written by David Ihnat. */
317 /* POSIX changes, bug fixes, long-named options, and cleanup
318 by David MacKenzie <djm@gnu.ai.mit.edu>.
320 Rewrite cut_fields and cut_bytes -- Jim Meyering. */
322 1992-11-08
323 Jim Meyering
330 Autoreninfo
332 Markus Schnalke interessiert sich fuer die Hintergruende
333 von Unix und seinen Werkzeugen. Fuer die Erarbeitung dieses
334 Textes wurde er regelrecht zum Historiker.
337 Lizenz
338 CC0 (und kann damit auch unter CC BY-SA 4.0 Unported
339 veroeffentlicht werden)