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