rev |
line source |
meillo@6
|
1 cut - cut out selected fields of each line of a file
|
meillo@6
|
2 ----------------------------------------------------
|
meillo@6
|
3 markus schnalke <meillo@marmaro.de>
|
meillo@6
|
4 2015-05
|
meillo@0
|
5
|
meillo@0
|
6
|
meillo@1
|
7 Cut ist ein klassisches Programm im Unix-Werkzeugkasten.
|
meillo@8
|
8 In keinem ordentlichen Tutorial zur Shellprogrammierung fehlt
|
meillo@21
|
9 es, denn es ist ein schönes, praktisches und anschauliches
|
meillo@9
|
10 Helferlein. Hier soll ein wenig hinter seine Fassade geschaut
|
meillo@9
|
11 werden.
|
meillo@0
|
12
|
meillo@0
|
13
|
meillo@4
|
14 Funktionsweise
|
meillo@4
|
15
|
meillo@21
|
16 Ursprünglich hatte cut zwei Modi, die später um einen dritten
|
meillo@21
|
17 erweitert wurden. Cut schneidet entweder gewünschte Zeichen aus
|
meillo@21
|
18 den Zeilen der Eingabe oder gewünschte, durch Trennzeichen
|
meillo@8
|
19 definierte, Felder.
|
meillo@0
|
20
|
meillo@9
|
21 Der Zeichenmodus ist optimal geeignet um Festbreitenformate zu
|
meillo@19
|
22 zerteilen. Man kann damit beispielsweise bestimmte
|
meillo@9
|
23 Zugriffsrechte aus der Ausgabe von `ls -l' ausschneiden, in
|
meillo@9
|
24 diesem Beispiel die Rechte des Besitzers:
|
meillo@0
|
25
|
meillo@15
|
26 $ ls -l foo
|
meillo@15
|
27 -rw-rw-r-- 1 meillo users 0 May 12 07:32 foo
|
meillo@15
|
28
|
meillo@4
|
29 $ ls -l foo | cut -c 2-4
|
meillo@4
|
30 rw-
|
meillo@0
|
31
|
meillo@4
|
32 Oder die Schreibrechte des Besitzers, der Gruppe und der
|
meillo@4
|
33 Welt:
|
meillo@0
|
34
|
meillo@4
|
35 $ ls -l | cut -c 3,6,9
|
meillo@4
|
36 ww-
|
meillo@0
|
37
|
meillo@21
|
38 Mit cut lassen sich aber auch Strings kürzen.
|
meillo@0
|
39
|
meillo@10
|
40 $ long=12345678901234567890
|
meillo@10
|
41 $ echo "$long" | cut -c -10
|
meillo@10
|
42 1234567890
|
meillo@0
|
43
|
meillo@10
|
44 Dieser Befehl gibt die ersten maximal 10 Zeichen von
|
meillo@21
|
45 `$long' aus. (Alternativ kann man hierfür `printf
|
meillo@10
|
46 "%.10s\n" "$long"' verwenden.)
|
meillo@0
|
47
|
meillo@4
|
48 Geht es aber nicht um die Darstellung von Zeichen, sondern um
|
meillo@8
|
49 ihre Speicherung, dann ist `-c' nicht unbedingt geeignet.
|
meillo@21
|
50 Früher, als US-ASCII noch die omnipräsente Zeichenkodierung
|
meillo@17
|
51 war, wurde jedes Zeichen mit genau einem
|
meillo@21
|
52 Byte gespeichert. Somit selektierte `cut -c' gleichermaßen
|
meillo@4
|
53 sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von
|
meillo@4
|
54 Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von
|
meillo@21
|
55 dieser Annahme lösen. In diesem Zug bekam cut mit
|
meillo@9
|
56 POSIX.2-1992 einen Bytemodus (Option `-b'). Will man
|
meillo@4
|
57 also nur die ersten maximal 500 Bytes vor dem
|
meillo@0
|
58 Newline-Zeichen stehen haben (und den Rest stillschweigend
|
meillo@0
|
59 ignorieren), dann macht man das mit:
|
meillo@0
|
60
|
meillo@6
|
61 $ cut -b -500
|
meillo@0
|
62
|
meillo@4
|
63 Den Rest kann man sich mit `cut -b 501-' einfangen. Diese
|
meillo@21
|
64 Funktion ist insbesondere für POSIX wichtig, da man damit
|
meillo@21
|
65 Textdateien mit begrenzter Zeilenlänge erzeugen kann.
|
meillo@4
|
66 [ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17
|
meillo@0
|
67
|
meillo@21
|
68 Wenn auch der Bytemodus neu eingeführt worden war, so sollte
|
meillo@17
|
69 er sich doch nur so verhalten wie der alte Zeichenmodus
|
meillo@17
|
70 normalerweise schon implementiert war. Beim Zeichenmodus aber
|
meillo@17
|
71 wurde eine neue Implementierungsweise gefordert. Das Problem
|
meillo@19
|
72 war folglich nicht, den neuen Bytemodus zu implementieren, sondern
|
meillo@10
|
73 den Zeichenmodus neu zu implementieren.
|
meillo@10
|
74
|
meillo@17
|
75 Neben dem Zeichen- und Bytemodus bietet cut noch den
|
meillo@17
|
76 Feldmodus, den man mit `-f' einleitet. Mit ihm
|
meillo@21
|
77 können Felder ausgewählt werden. Das Trennzeichen (per
|
meillo@21
|
78 Default der Tab) kann mit `-d' geändert werden. Es gilt in
|
meillo@21
|
79 gleicher Weise für die Eingabe und die Ausgabe.
|
meillo@0
|
80
|
meillo@21
|
81 Der typische Anwendungsfall für cut im Feldmodus ist die
|
meillo@19
|
82 Auswahl von Information aus der passwd-Datei. Hier z.B. der
|
meillo@17
|
83 Benutzername und seine ID:
|
meillo@0
|
84
|
meillo@17
|
85 $ cut -d: -f1,3 /etc/passwd
|
meillo@17
|
86 root:0
|
meillo@17
|
87 bin:1
|
meillo@17
|
88 daemon:2
|
meillo@17
|
89 mail:8
|
meillo@9
|
90 ...
|
meillo@0
|
91
|
meillo@21
|
92 (Die Argumente für die Optionen können bei cut übrigens
|
meillo@21
|
93 mit Whitespace abgetrennt oder direkt angehängt folgen.)
|
meillo@0
|
94
|
meillo@21
|
95 Dieser Feldmodus ist für einfache tabellarische Dateien,
|
meillo@4
|
96 wie eben die passwd, gut geeignet. Er kommt aber schnell an
|
meillo@21
|
97 seine Grenzen. Gerade der häufige Fall, dass an Whitespace
|
meillo@0
|
98 in Felder geteilt werden soll, wird damit nicht abgedeckt.
|
meillo@17
|
99 Der Delimiter kann bei cut nur genau ein Zeichen sein. Es kann
|
meillo@19
|
100 demnach nicht sowohl an Leerzeichen als auch an Tabs aufgetrennt
|
meillo@19
|
101 werden. Zudem unterteilt cut an jedem Trennzeichen. Zwei aneinander
|
meillo@21
|
102 stehende Trennzeichen führen zu einem leeren Feld. Dieses
|
meillo@8
|
103 Verhalten widerspricht den Erwartungen, die man an die
|
meillo@8
|
104 Verarbeitung einer Datei mit Whitespace-getrennten Feldern
|
meillo@8
|
105 hat. Manche Implementierungen von cut, z.B. die von FreeBSD,
|
meillo@21
|
106 haben deshalb Erweiterungen, die das gewünschte Verhalten
|
meillo@21
|
107 für Whitespace-getrennte Felder bieten. Ansonsten, d.h. wenn
|
meillo@9
|
108 man portabel bleiben will, verwendet man awk in diesen
|
meillo@21
|
109 Fällen.
|
meillo@0
|
110
|
meillo@4
|
111 Awk bietet noch eine weitere Funktion, die cut missen
|
meillo@21
|
112 lässt: Das Tauschen der Feld-Reihenfolge in der Ausgabe. Bei
|
meillo@8
|
113 cut ist die Reihenfolge der Feldauswahlangabe irrelevant; ein
|
meillo@19
|
114 Feld kann selbst mehrfach angegeben werden. Dementsprechend gibt
|
meillo@19
|
115 der Aufruf
|
meillo@8
|
116 von `cut -c 5-8,1,4-6' die Zeichen Nummer 1, 4, 5, 6, 7 und 8
|
meillo@8
|
117 in genau dieser Reihenfolge aus. Die Auswahl entspricht damit
|
meillo@8
|
118 der Mengenlehre in der Mathematik: Jedes angegebene Feld wird
|
meillo@9
|
119 Teil der Ergebnismenge. Die Felder der Ergebnismenge sind
|
meillo@19
|
120 hierbei immer gleich geordnet wie in der Eingabe. Um die Worte
|
meillo@16
|
121 der Manpage von Version 8 Unix wiederzugeben: ``In data base
|
meillo@9
|
122 parlance, it projects a relation.''
|
meillo@16
|
123 [ http://man.cat-v.org/unix_8th/1/cut
|
meillo@21
|
124 Cut führt demnach die Datenbankoperation Projektion auf
|
meillo@21
|
125 Textdateien aus. Die Wikipedia erklärt das folgendermaßen:
|
meillo@7
|
126
|
meillo@7
|
127 Die Projektion entspricht der Projektionsabbildung aus der
|
meillo@7
|
128 Mengenlehre und kann auch Attributbeschränkung genannt
|
meillo@7
|
129 werden. Sie extrahiert einzelne Attribute aus der
|
meillo@7
|
130 ursprünglichen Attributmenge und ist somit als eine Art
|
meillo@7
|
131 Selektion auf Spaltenebene zu verstehen, das heißt, die
|
meillo@7
|
132 Projektion blendet Spalten aus.
|
meillo@7
|
133
|
meillo@8
|
134 [ http://de.wikipedia.org/wiki/Projektion_(Informatik)#Projektion
|
meillo@8
|
135
|
meillo@7
|
136
|
meillo@0
|
137 Geschichtliches
|
meillo@0
|
138
|
meillo@4
|
139 Cut erblickte 1982 mit dem Release von UNIX System III das
|
meillo@21
|
140 Licht der öffentlichen Welt. Wenn man die Quellen von System
|
meillo@22
|
141 III durchforstet, findet man cut.c mit dem Zeitstempel 1980-04-11.
|
meillo@1
|
142 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd
|
meillo@22
|
143 Das ist die älteste Implementierung des Programms, die ich
|
meillo@21
|
144 aufstöbern konnte. Allerdings spricht die SCCS-ID im
|
meillo@22
|
145 Quellcode von Version 1.5. Die Vorgeschichte liegt, der Vermutung
|
meillo@20
|
146 Doug McIlroys
|
meillo@22
|
147 [ http://minnie.tuhs.org/pipermail/tuhs/2015-May/004083.html
|
meillo@22
|
148 zufolge, in PWB/UNIX, dessen Entwicklungslinie die Grundlage für
|
meillo@22
|
149 System III war. In den von PWB 1.0 (1977) verfügbaren Quellen
|
meillo@22
|
150 [ http://minnie.tuhs.org/Archive/PDP-11/Distributions/usdl/
|
meillo@23
|
151 ist cut noch nicht zu finden. Von PWB 2.0 scheinen keine
|
meillo@23
|
152 Quellen oder hilfreiche Dokumentation verfügbar zu sein.
|
meillo@22
|
153 PWB 3.0 wurde später aus Marketinggründen als System III
|
meillo@24
|
154 bezeichnet und ist folglich mit ihm identisch. Eine Nebenlinie zu
|
meillo@24
|
155 PWB war CB Unix, das nur innerhalb
|
meillo@22
|
156 der Bell Labs genutzt wurde. Das Handbuch von CB Unix Edition 2.1
|
meillo@24
|
157 vom November 1979 enthält die früheste Erwähnung von cut, die
|
meillo@24
|
158 meine Recherche zutage gefördert hat: eine Manpage für cut.
|
meillo@22
|
159 [ ftp://sunsite.icm.edu.pl/pub/unix/UnixArchive/PDP-11/Distributions/other/CB_Unix/cbunix_man1_02.pdf
|
meillo@0
|
160
|
meillo@24
|
161 Nun ein Blick auf die BSD-Linie: Dort ist der früheste
|
meillo@17
|
162 Fund ein cut.c mit dem Dateimodifikationsdatum 1986-11-07
|
meillo@8
|
163 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut
|
meillo@8
|
164 als Teil der Spezialversion 4.3BSD-UWisc,
|
meillo@6
|
165 [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix
|
meillo@21
|
166 die im Januar 1987 veröffentlicht wurde.
|
meillo@8
|
167 Die Implementierung unterscheidet sich nur minimal von der
|
meillo@8
|
168 in System III.
|
meillo@17
|
169 Im bekannteren 4.3BSD-Tahoe (1988) tauchte cut nicht auf.
|
meillo@17
|
170 Das darauf folgende 4.3BSD-Reno (1990) lieferte aber wieder
|
meillo@17
|
171 ein cut mit aus. Dieses cut war ein von Adam S. Moskowitz und
|
meillo@8
|
172 Marciano Pitargue neu implementiertes cut, das 1989 in BSD
|
meillo@8
|
173 aufgenommen wurde.
|
meillo@1
|
174 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut
|
meillo@4
|
175 Seine Manpage
|
meillo@1
|
176 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1
|
meillo@21
|
177 erwähnt bereits die erwartete Konformität mit POSIX.2.
|
meillo@17
|
178 Nun muss man wissen, dass POSIX.2 erst im September
|
meillo@21
|
179 1992 veröffentlicht wurde, erst gut zwei Jahren nachdem die
|
meillo@17
|
180 Manpage und das Programm geschrieben worden waren. Das Programm
|
meillo@10
|
181 wurde folglich anhand von Arbeitsversionen des Standards
|
meillo@21
|
182 implementiert. Ein Blick in den Code bekräftigt diese Vermutung.
|
meillo@15
|
183 In der Funktion zum parsen der Feldauswahlliste findet sich
|
meillo@15
|
184 dieser Kommentar:
|
meillo@0
|
185
|
meillo@15
|
186 This parser is less restrictive than the Draft 9 POSIX spec.
|
meillo@15
|
187 POSIX doesn't allow lists that aren't in increasing order or
|
meillo@15
|
188 overlapping lists.
|
meillo@9
|
189
|
meillo@21
|
190 Im Draft 11.2 (1991-09) fordert POSIX diese Flexibilität bereits
|
meillo@15
|
191 ein:
|
meillo@12
|
192
|
meillo@15
|
193 The elements in list can be repeated, can overlap, and can
|
meillo@15
|
194 be specified in any order.
|
meillo@15
|
195
|
meillo@21
|
196 Zudem listet Draft 11.2 alle drei Modi, während in diesem
|
meillo@21
|
197 BSD cut nur die zwei alten implementiert sind. Es könnte also
|
meillo@17
|
198 sein, dass in Draft 9 der Bytemodus noch nicht vorhanden war.
|
meillo@23
|
199 Ohne Zugang zu Draft 9 oder 10, war es leider nicht möglich,
|
meillo@23
|
200 diese Vermutung zu prüfen.
|
meillo@17
|
201
|
meillo@21
|
202 Die Versionsnummern und Änderungsdaten der älteren
|
meillo@17
|
203 BSD-Implementierungen kann man aus den SCCS-IDs, die vom
|
meillo@21
|
204 damaligen Versionskontrollsystem in den Code eingefügt wurden,
|
meillo@15
|
205 ablesen. So z.B. bei 4.3BSD-Reno: ``5.3 (Berkeley) 6/24/90''.
|
meillo@12
|
206
|
meillo@21
|
207 Das cut der GNU Coreutils enthält folgenden Copyrightvermerk:
|
meillo@12
|
208
|
meillo@12
|
209 Copyright (C) 1997-2015 Free Software Foundation, Inc.
|
meillo@12
|
210 Copyright (C) 1984 David M. Ihnat
|
meillo@12
|
211
|
meillo@21
|
212 Der Code hat also recht alte Ursprünge. Wie aus weiteren
|
meillo@17
|
213 Kommentaren zu entnehmen ist, wurde der Programmcode zuerst von David
|
meillo@21
|
214 MacKenzie und später von Jim Meyering überarbeitet. Letzterer
|
meillo@12
|
215 hat den Code 1992 auch ins Versionkontrollsystem eingestellt.
|
meillo@17
|
216 Weshalb die Jahre vor 1997, zumindest ab 1992, nicht im
|
meillo@17
|
217 Copyright-Vermerk auftauchen, ist unklar.
|
meillo@12
|
218
|
meillo@21
|
219 Trotz der vielen Jahreszahlen aus den 80er Jahren gehört cut,
|
meillo@21
|
220 aus Sicht des ursprünglichen Unix, zu den jüngeren Tools.
|
meillo@21
|
221 Wenn cut auch ein Jahrzehnt älter als Linux, der Kernel, ist,
|
meillo@23
|
222 so war Unix schon über zehn Jahre alt, als cut das
|
meillo@21
|
223 erste Mal auftauchte. Insbesondere gehörte cut noch nicht
|
meillo@4
|
224 zu Version 7 Unix, das die Ausgangsbasis aller modernen
|
meillo@4
|
225 Unix-Systeme darstellt. Die weit komplexeren Programme sed
|
meillo@23
|
226 und awk waren dort aber schon vertreten. Man muss sich also
|
meillo@21
|
227 fragen, warum cut überhaupt noch entwickelt wurde, wo es
|
meillo@9
|
228 schon zwei Programme gab, die die Funktion von cut abdecken
|
meillo@21
|
229 konnten. Ein Argument für cut war sicher seine Kompaktheit und
|
meillo@21
|
230 die damit verbundene Geschwindigkeit gegenüber dem damals
|
meillo@21
|
231 trägen awk. Diese schlanke Gestalt ist es auch, die der
|
meillo@17
|
232 Unix-Philosopie entspricht: Mache eine Aufgabe und die richtig!
|
meillo@21
|
233 Cut überzeugte. Es wurde in andere Unix Varianten übernommen,
|
meillo@21
|
234 standardisiert und ist heutzutage überall anzutreffen.
|
meillo@1
|
235
|
meillo@21
|
236 Die ursprüngliche Variante (ohne -b) wurde schon 1985 in
|
meillo@5
|
237 der System V Interface Definition, einer wichtigen formalen
|
meillo@9
|
238 Beschreibung von UNIX System V, spezifiziert und tauchte
|
meillo@21
|
239 anschließend in allen relevanten Standards auf. Mit POSIX.2
|
meillo@9
|
240 im Jahre 1992 wurde cut zum ersten Mal in der heutigen Form
|
meillo@9
|
241 (mit -b) standardisiert.
|
meillo@1
|
242
|
meillo@1
|
243
|
meillo@21
|
244 Multibyte-Unterstützung
|
meillo@8
|
245
|
meillo@8
|
246 Nun sind der Bytemodus und die damit verbundene
|
meillo@8
|
247 Multibyte-Verarbeitung des POSIX-Zeichenmodus bereits seit
|
meillo@8
|
248 1992 standardisiert, wie steht es aber mit deren Umsetzung?
|
meillo@10
|
249 Welche Versionen implementieren POSIX korrekt?
|
meillo@17
|
250 Die Situation ist dreiteilig: Es gibt historische
|
meillo@8
|
251 Implementierungen, die nur -c und -f kennen. Dann gibt es
|
meillo@10
|
252 Implementierungen die -b zwar kennen, es aber lediglich als Alias
|
meillo@21
|
253 für -c handhaben. Diese Implementierungen funktionieren mit
|
meillo@8
|
254 Single-Byte-Encodings (z.B. US-ASCII, Latin1) korrekt, bei
|
meillo@21
|
255 Multibyte-Encodings (z.B. UTF-8) verhält sich ihr -c aber
|
meillo@21
|
256 wie -b (und -n wird ignoriert). Schließlich gibt es noch
|
meillo@21
|
257 Implementierungen, die -b und -c tatsächlich POSIX-konform
|
meillo@8
|
258 implementieren.
|
meillo@8
|
259
|
meillo@17
|
260 Historische Zwei-Modi-Implementierungen sind z.B. die von
|
meillo@8
|
261 System III, System V und die aller BSDs bis in die 90er.
|
meillo@8
|
262
|
meillo@10
|
263 Pseudo-Multibyte-Implementierungen bieten GNU und die
|
meillo@17
|
264 modernen NetBSDs und OpenBSDs. Man darf sich sicher fragen,
|
meillo@21
|
265 ob dort ein Schein von POSIX-Konformität gewahrt wird.
|
meillo@15
|
266 Teilweise findet man erst nach genauerer Suche heraus, dass
|
meillo@15
|
267 -c und -n nicht wie erwartet funktionieren; teilweise machen es
|
meillo@17
|
268 sich die Systeme auch einfach, indem sie auf
|
meillo@23
|
269 Singlebyte-Zeichenkodierungen beharren, das aber dafür
|
meillo@17
|
270 klar darlegen:
|
meillo@8
|
271
|
meillo@15
|
272 Since we don't support multi-byte characters, the -c and -b
|
meillo@15
|
273 options are equivalent, and the -n option is meaningless.
|
meillo@8
|
274
|
meillo@16
|
275 [ http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/cut/cut.c?rev=1.18&content-type=text/x-cvsweb-markup
|
meillo@8
|
276
|
meillo@21
|
277 Tatsächlich standardkonforme Implementierungen, die
|
meillo@8
|
278 Multibytes korrekt handhaben, bekommt man bei einem modernen
|
meillo@8
|
279 FreeBSD und bei den Heirloom Tools. Bei FreeBSD hat Tim Robbins
|
meillo@9
|
280 im Sommer 2004 den Zeichenmodus POSIX-konform reimplementiert.
|
meillo@8
|
281 [ https://svnweb.freebsd.org/base?view=revision&revision=131194
|
meillo@21
|
282 Warum die beiden anderen großen BSDs diese Änderung nicht
|
meillo@21
|
283 übernommen haben, bleibt offen. Es scheint aber an der im
|
meillo@8
|
284 obigen Kommentar formulierten Grundausrichtung zu liegen.
|
meillo@8
|
285
|
meillo@23
|
286 Wie findet man nun als Nutzer heraus, ob beim cut des eigenen
|
meillo@21
|
287 Systems Multibytes korrekt unterstützt werden? Zuerst ist
|
meillo@8
|
288 entscheidend, ob das System selbst mit einem Multibyte-Encoding
|
meillo@17
|
289 arbeitet, denn tut es das nicht, dann entsprechen sich
|
meillo@21
|
290 Zeichen und Bytes und die Frage erübrigt sich. Man kann das
|
meillo@9
|
291 herausfinden indem man sich das Locale anschaut, aber einfacher
|
meillo@9
|
292 ist es, ein typisches Mehrbytezeichen, wie z.B. einen Umlaut,
|
meillo@9
|
293 auszugeben und zu schauen ob dieses in einem oder in mehreren
|
meillo@9
|
294 Bytes kodiert ist:
|
meillo@8
|
295
|
meillo@8
|
296 $ echo ä | od -c
|
meillo@8
|
297 0000000 303 244 \n
|
meillo@8
|
298 0000003
|
meillo@8
|
299
|
meillo@8
|
300 In diesem Fall sind es zwei Bytes: oktal 303 und 244 . (Den
|
meillo@23
|
301 Zeilenumbruch fügt echo hinzu.)
|
meillo@8
|
302
|
meillo@23
|
303 Mit dem Programm iconv kann man Text explizit in bestimmte
|
meillo@10
|
304 Kodierungen konvertieren. Hier Beispiele, wie die Ausgabe
|
meillo@10
|
305 bei Latin1 und wie sie bei UTF-8 aussieht.
|
meillo@8
|
306
|
meillo@8
|
307 $ echo ä | iconv -t latin1 | od -c
|
meillo@8
|
308 0000000 344 \n
|
meillo@8
|
309 0000002
|
meillo@8
|
310
|
meillo@8
|
311 $ echo ä | iconv -t utf8 | od -c
|
meillo@8
|
312 0000000 303 244 \n
|
meillo@8
|
313 0000003
|
meillo@8
|
314
|
meillo@8
|
315 Die Ausgabe auf dem eigenen System (ohne die iconv-Konvertierung)
|
meillo@8
|
316 wird recht sicher einer dieser beiden Ausgaben entsprechen.
|
meillo@8
|
317
|
meillo@8
|
318 Nun zum Test der cut-Implementierung. Hat man ein UTF-8-System,
|
meillo@21
|
319 dann sollte sich eine POSIX-konforme Implementierung folgendermaßen
|
meillo@17
|
320 verhalten:
|
meillo@8
|
321
|
meillo@18
|
322 $ echo ä | cut -c 1 | od -c
|
meillo@10
|
323 0000000 303 244 \n
|
meillo@8
|
324 0000003
|
meillo@8
|
325
|
meillo@18
|
326 $ echo ä | cut -b 1 | od -c
|
meillo@10
|
327 0000000 303 \n
|
meillo@8
|
328 0000002
|
meillo@8
|
329
|
meillo@18
|
330 $ echo ä | cut -b 1 -n | od -c
|
meillo@10
|
331 0000000 \n
|
meillo@10
|
332 0000001
|
meillo@10
|
333
|
meillo@10
|
334 Bei einer Pseudo-POSIX-Implementierung ist die Ausgabe in
|
meillo@21
|
335 allen drei Fällen wie die mittlere: Es wird das erste Byte
|
meillo@10
|
336 ausgegeben.
|
meillo@8
|
337
|
meillo@8
|
338
|
meillo@8
|
339 Implementierungen
|
meillo@8
|
340
|
meillo@9
|
341 Nun ein Blick auf den Code. Betrachtet wird eine Auswahl an
|
meillo@9
|
342 Implementierungen.
|
meillo@9
|
343
|
meillo@21
|
344 Für einen ersten Eindruck ist der Umfang des Quellcodes
|
meillo@21
|
345 hilfreich. Typischerweise steigt dieser über die Jahre an. Diese
|
meillo@8
|
346 Beobachtung kann hier in der Tendenz, aber nicht in jedem Fall,
|
meillo@21
|
347 bestätigt werden. Die POSIX-konforme Umsetzung des Zeichenmodus
|
meillo@21
|
348 erfordert zwangsläufig mehr Code, deshalb sind diese
|
meillo@17
|
349 Implementierungen tendenziell umfangreicher.
|
meillo@8
|
350
|
meillo@8
|
351
|
meillo@21
|
352 SLOC Zeilen Bytes Gehört zu Dateidatum Kategorie
|
meillo@9
|
353 -----------------------------------------------------------------
|
meillo@17
|
354 116 123 2966 System III 1980-04-11 (hist)
|
meillo@17
|
355 118 125 3038 4.3BSD-UWisc 1986-11-07 (hist)
|
meillo@17
|
356 200 256 5715 4.3BSD-Reno 1990-06-25 (hist)
|
meillo@17
|
357 200 270 6545 NetBSD 1993-03-21 (hist)
|
meillo@9
|
358 218 290 6892 OpenBSD 2008-06-27 (pseudo)
|
meillo@17
|
359 224 296 6920 FreeBSD 1994-05-27 (hist)
|
meillo@9
|
360 232 306 7500 NetBSD 2014-02-03 (pseudo)
|
meillo@9
|
361 340 405 7423 Heirloom 2012-05-20 (POSIX)
|
meillo@9
|
362 382 586 14175 GNU coreutils 1992-11-08 (pseudo)
|
meillo@9
|
363 391 479 10961 FreeBSD 2012-11-24 (POSIX)
|
meillo@9
|
364 588 830 23167 GNU coreutils 2015-05-01 (pseudo)
|
meillo@8
|
365
|
meillo@8
|
366
|
meillo@9
|
367 Das Kandidatenfeld teilt sich grob in vier Gruppen: (1) Die zwei
|
meillo@21
|
368 ursprünglichen Implementierungen, die sich nur minimal
|
meillo@21
|
369 unterscheiden, mit gut 100 SLOCs. (2) Die fünf BSD-Versionen mit
|
meillo@9
|
370 gut 200 SLOCs. (3) Die zwei POSIX-konformen Programme und
|
meillo@21
|
371 die alte GNU-Version mit 340-390 SLOCs. Und schließlich (4) die
|
meillo@17
|
372 moderne GNU-Variante mit fast 600 SLOCs.
|
meillo@8
|
373
|
meillo@9
|
374 Die Abweichung zwischen logischen Codezeilen (SLOC, ermittelt mit
|
meillo@21
|
375 SLOCcount) und der Anzahl von Zeilenumbrüchen in der Datei (`wc
|
meillo@21
|
376 -l') erstreckt sich über eine Spanne von Faktor 1.06 bei den
|
meillo@21
|
377 ältesten Vertretern bis zu Faktor 1.5 bei GNU. Den größten
|
meillo@19
|
378 Einfluss darauf haben Leerzeilen, reine Kommentarzeilen und
|
meillo@21
|
379 die Größe des Lizenzblocks am Dateianfang.
|
meillo@8
|
380
|
meillo@9
|
381 Betrachtet man die Abweichungen zwischen den logischen Codezeilen
|
meillo@21
|
382 und der Dateigröße (`wc -c'), so pendelt das Teilnehmerfeld
|
meillo@9
|
383 zwischen 25 und 30 Bytes je Anweisung. Die Heirloom-Implementierung
|
meillo@9
|
384 weicht mit nur 21 nach unten ab, die GNU-Implementierungen mit
|
meillo@21
|
385 fast 40 nach oben. Bei GNU liegt dies hauptsächlich an deren
|
meillo@21
|
386 Programmierstil, mit spezieller Einrückung und langen Bezeichnern.
|
meillo@21
|
387 Ob man die Heirloom-Implementierung
|
meillo@22
|
388 [ http://heirloom.cvs.sourceforge.net/viewvc/heirloom/heirloom/cut/cut.c?revision=1.6&view=markup
|
meillo@21
|
389 als besonders kryptisch
|
meillo@9
|
390 oder als besonders elegant bezeichnen will, das soll der
|
meillo@21
|
391 eigenen Einschätzung des Lesers überlassen bleiben. Vor allem
|
meillo@21
|
392 der Vergleich mit einer GNU-Implementierung
|
meillo@22
|
393 [ http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/cut.c;hb=e981643
|
meillo@21
|
394 ist eindrucksvoll.
|
meillo@8
|
395
|
meillo@8
|
396
|
meillo@21
|
397 Die interne Struktur der Programmcodes (in C) ist meist ähnlich.
|
meillo@17
|
398 Neben der obligatorischen main-Funktion, die die Kommandozeilenargumente
|
meillo@11
|
399 verarbeitet, gibt es im Normalfall eine Funktion, die die
|
meillo@21
|
400 Feldauswahl in eine interne Datenstruktur überführt. Desweiteren
|
meillo@23
|
401 haben fast alle Implementierungen separate Funktionen für jeden
|
meillo@23
|
402 ihrer Modi. Bei den POSIX-konformen Implementierungen
|
meillo@11
|
403 wird die `-b -n'-Kombination als weiterer Modus behandelt, und
|
meillo@21
|
404 damit in einer eigenen Funktion umgesetzt. Nur bei der frühen
|
meillo@11
|
405 System III-Implementierung (und seiner 4.3BSD-UWisc-Variante)
|
meillo@21
|
406 wird außer den Fehlerausgaben alles in der main-Funktion
|
meillo@17
|
407 erledigt.
|
meillo@11
|
408
|
meillo@15
|
409 Cut-Implementierungen haben typischerweise zwei limitierende
|
meillo@21
|
410 Größen: Die Maximalanzahl unterstützter Felder und die maximale
|
meillo@21
|
411 Zeilenlänge. Bei System III sind beide Größen auf 512 begrenzt.
|
meillo@17
|
412 4.3BSD-Reno und die BSDs der 90er Jahre haben ebenfalls fixe
|
meillo@17
|
413 Grenzen (_BSD_LINE_MAX bzw. _POSIX2_LINE_MAX). Bei modernen
|
meillo@17
|
414 FreeBSDs, NetBSDs, bei allen GNU-Implementierungen und bei
|
meillo@17
|
415 Heirloom kann sowohl die Felderanzahl als auch die maximale
|
meillo@21
|
416 Zeilenlänge beliebig groß werden; der Speicher dafür wird
|
meillo@17
|
417 dynamisch alloziiert. OpenBSD ist ein Hybrid aus fixer
|
meillo@21
|
418 Maximalzahl an Feldern, aber beliebiger Zeilenlänge. Die
|
meillo@17
|
419 begrenzte Felderanzahl scheint jedoch kein Praxisproblem
|
meillo@17
|
420 darzustellen, da _POSIX2_LINE_MAX mit mindestens 2048 durchaus
|
meillo@21
|
421 groß genug sein sollte.
|
meillo@11
|
422
|
meillo@8
|
423
|
meillo@2
|
424 Beschreibungen
|
meillo@1
|
425
|
meillo@19
|
426 Interessant ist zudem ein Vergleich der Kurzbeschreibungen von
|
meillo@17
|
427 cut, wie sie sich in der Titelzeile der Manpages oder manchmal
|
meillo@19
|
428 am Anfang der Quellcodedatei finden. Die folgende Liste
|
meillo@9
|
429 ist grob zeitlich geordnet und nach Abstammung gruppiert:
|
meillo@3
|
430
|
meillo@3
|
431
|
meillo@22
|
432 CB Unix cut out selected fields of each line of a file
|
meillo@2
|
433 System III cut out selected fields of each line of a file
|
meillo@3
|
434 System III (src) cut and paste columns of a table (projection of a relation)
|
meillo@2
|
435 System V cut out selected fields of each line of a file
|
meillo@2
|
436 HP-UX cut out (extract) selected fields of each line of a file
|
meillo@2
|
437
|
meillo@3
|
438 4.3BSD-UWisc (src) cut and paste columns of a table (projection of a relation)
|
meillo@2
|
439 4.3BSD-Reno select portions of each line of a file
|
meillo@2
|
440 NetBSD select portions of each line of a file
|
meillo@7
|
441 OpenBSD 4.6 select portions of each line of a file
|
meillo@2
|
442 FreeBSD 1.0 select portions of each line of a file
|
meillo@10
|
443 FreeBSD 10.0 cut out selected portions of each line of a file
|
meillo@2
|
444 SunOS 4.1.3 remove selected fields from each line of a file
|
meillo@2
|
445 SunOS 5.5.1 cut out selected fields of each line of a file
|
meillo@2
|
446
|
meillo@8
|
447 Heirloom Tools cut out selected fields of each line of a file
|
meillo@9
|
448 Heirloom Tools (src) cut out fields of lines of files
|
meillo@2
|
449
|
meillo@2
|
450 GNU coreutils remove sections from each line of files
|
meillo@2
|
451
|
meillo@2
|
452 Minix select out columns of a file
|
meillo@2
|
453
|
meillo@2
|
454 Version 8 Unix rearrange columns of data
|
meillo@2
|
455 ``Unix Reader'' rearrange columns of text
|
meillo@2
|
456
|
meillo@9
|
457 POSIX cut out selected fields of each line of a file
|
meillo@2
|
458
|
meillo@9
|
459
|
meillo@9
|
460 Die mit ``(src)'' markierten Beschreibungen sind aus dem
|
meillo@21
|
461 jeweiligen Quellcode entnommen. Der POSIX-Eintrag enthält
|
meillo@18
|
462 die Beschreibung im Standard. Der ``Unix Reader'' ist ein
|
meillo@21
|
463 rückblickendes Textdokument von Doug McIlroy, das das
|
meillo@18
|
464 Auftreten der Tools in der Geschichte des Research Unix zum
|
meillo@17
|
465 Thema hat.
|
meillo@16
|
466 [ http://doc.cat-v.org/unix/unix-reader/contents.pdf
|
meillo@17
|
467 Eigentlich sollte seine Beschreibung der in Version 8 Unix
|
meillo@21
|
468 entsprechen. Die Abweichung könnte ein Übertragungsfehler
|
meillo@21
|
469 oder eine nachträgliche Korrektur sein. Alle übrigen
|
meillo@19
|
470 Beschreibungen entstammen den Manpages.
|
meillo@5
|
471
|
meillo@21
|
472 Oft ist mit der Zeit die POSIX-Beschreibung übernommen
|
meillo@17
|
473 oder an sie angeglichen worden, wie beispielsweise bei FreeBSD.
|
meillo@5
|
474 [ https://svnweb.freebsd.org/base?view=revision&revision=167101
|
meillo@5
|
475
|
meillo@7
|
476 Interessant ist, dass die GNU coreutils seit Anbeginn vom
|
meillo@5
|
477 Entfernen von Teilen der Eingabe sprechen, wohingegen die
|
meillo@21
|
478 Kommandozeilenangabe klar ein Auswählen darstellt. Die
|
meillo@21
|
479 Worte ``cut out'' sind vielleicht auch zu missverständlich.
|
meillo@21
|
480 HP-UX hat sie deshalb präzisiert.
|
meillo@5
|
481
|
meillo@19
|
482 Beim Begriff, was selektiert wird, ist man sich ebenfalls
|
meillo@17
|
483 uneins. Die Einen reden von Feldern (POSIX), Andere von
|
meillo@17
|
484 Abschnitten bzw. Teilen (BSD) und wieder Andere von Spalten
|
meillo@25
|
485 (Research Unix). Die scheinbar unzutreffende Beschreibung
|
meillo@25
|
486 bei Version 8 Unix (``rearrange columns of data'') ist
|
meillo@25
|
487 dadurch zu erklären, dass die Manpage sowohl cut als auch
|
meillo@25
|
488 paste abdeckt. In ihrer Kombination können tatsächlich
|
meillo@25
|
489 Spalten umgeordnet werden.
|
meillo@5
|
490
|
meillo@5
|
491
|
meillo@6
|
492 Autoreninfo
|
meillo@6
|
493
|
meillo@21
|
494 Markus Schnalke interessiert sich für die Hintergründe
|
meillo@21
|
495 von Unix und seinen Werkzeugen. Für die Erarbeitung dieses
|
meillo@6
|
496 Textes wurde er regelrecht zum Historiker.
|
meillo@6
|
497
|
meillo@6
|
498
|
meillo@6
|
499 Lizenz
|
meillo@10
|
500
|
meillo@6
|
501 CC0 (und kann damit auch unter CC BY-SA 4.0 Unported
|
meillo@21
|
502 veröffentlicht werden)
|