comparison cut.txt @ 8:1dc4a9dca829

Zwischenstand
author markus schnalke <meillo@marmaro.de>
date Tue, 05 May 2015 09:04:00 +0200
parents 21ca59543b07
children e67bd0d48bd6
comparison
equal deleted inserted replaced
7:21ca59543b07 8:1dc4a9dca829
5 markus schnalke <meillo@marmaro.de> 5 markus schnalke <meillo@marmaro.de>
6 2015-05 6 2015-05
7 7
8 8
9 Cut ist ein klassisches Programm im Unix-Werkzeugkasten. 9 Cut ist ein klassisches Programm im Unix-Werkzeugkasten.
10 In keinem ordentlichen Tutorial zur Shellprogrammierung darf 10 In keinem ordentlichen Tutorial zur Shellprogrammierung fehlt
11 es fehlen. Es ist ein schoenes Anschauungs- und Beispielobjekt 11 es. Es ist ein schoenes Anschauungsobjekt fuer's Shellscripting.
12 fuer's Shellscripting. Hier will ich ein wenig hinter die 12 Hier soll ein wenig hinter die Fassade von cut geschaut werden.
13 Fassade schauen.
14 13
15 14
16 Funktionsweise 15 Funktionsweise
17 16
18 Die Funktionsbasis von cut waren urspruenglich zwei Modi, die 17 Urspruenglich hatte cut zwei Modi, die spaeter um einen dritten
19 spaeter um einen dritten erweitert wurden. Cut schneidet 18 erweitert wurden. Cut schneidet entweder bestimmte Zeichen aus
20 entweder bestimmte Zeichen aus den Zeilen der Eingabe oder 19 den Zeilen der Eingabe oder bestimmte, durch Trennzeichen
21 bestimmte durch Trennzeichen definierte Felder. 20 definierte, Felder.
22 21
23 Der Zeichenmodus ist geeignet um Ausschnitte aus 22 Der Zeichenmodus ist geeignet um Festbreitenformaten zu
24 Festbreitenformaten zu extrahieren. So kann man damit 23 zerteilen. So kann man damit beispielsweise bestimmte
25 beispielsweise bestimmte Zugriffsrechte aus der Ausgabe von 24 Zugriffsrechte aus der Ausgabe von `ls -l' ausschneiden. Hier
26 `ls -l' ausschneiden. Hier die Rechte des Besitzers: 25 die Rechte des Besitzers:
27 26
28 $ ls -l foo | cut -c 2-4 27 $ ls -l foo | cut -c 2-4
29 rw- 28 rw-
30 29
31 Oder die Schreibrechte des Besitzers, der Gruppe und der 30 Oder die Schreibrechte des Besitzers, der Gruppe und der
36 35
37 Mit cut lassen sich aber auch Strings kuerzen. 36 Mit cut lassen sich aber auch Strings kuerzen.
38 37
39 $ echo "$long" | cut -c -20 38 $ echo "$long" | cut -c -20
40 39
41 Dieser Befehl gibt die ersten maximal 20 Zeichen (jeder 40 Dieser Befehl gibt die ersten maximal 20 Zeichen von
42 Zeile) von `$long' aus. 41 `$long' aus. (Alternativ kann man hierfuer auch `printf
42 "%.20s\n" "$long"' verwenden.)
43 43
44 Geht es aber nicht um die Darstellung von Zeichen, sondern um 44 Geht es aber nicht um die Darstellung von Zeichen, sondern um
45 ihre Speicherung, dann ist `-c' nicht unbedingt die passende 45 ihre Speicherung, dann ist `-c' nicht unbedingt geeignet.
46 Option. Frueher, als US-ASCII als Zeichensatz und -kodierung 46 Frueher, als US-ASCII als Zeichensatz und -kodierung
47 noch omnipraesent war, wurde jedes Zeichen mit genau einem 47 noch omnipraesent war, wurde jedes Zeichen mit genau einem
48 Byte gespeichert. Somit selektierte `cut -c' gleichermassen 48 Byte gespeichert. Somit selektierte `cut -c' gleichermassen
49 sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von 49 sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von
50 Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von 50 Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von
51 dieser Annahme loesen. In diesem Zug bekam cut mit 51 dieser Annahme loesen. In diesem Zug bekam cut mit
52 POSIX.2-1992 die Option `-b'. Diese selektiert Bytes. Will man 52 POSIX.2-1992 einen Bytemodus mit der Option `-b'. Will man
53 also nur die ersten maximal 500 Bytes vor dem 53 also nur die ersten maximal 500 Bytes vor dem
54 Newline-Zeichen stehen haben (und den Rest stillschweigend 54 Newline-Zeichen stehen haben (und den Rest stillschweigend
55 ignorieren), dann macht man das mit: 55 ignorieren), dann macht man das mit:
56 56
57 $ cut -b -500 57 $ cut -b -500
58 58
59 Den Rest kann man sich mit `cut -b 501-' einfangen. Diese 59 Den Rest kann man sich mit `cut -b 501-' einfangen. Diese
60 Funktion ist insbesondere fuer POSIX wichtig, da so sicher 60 Funktion ist insbesondere fuer POSIX wichtig, da man so
61 gestellt werden kann, dass Textdateien keine beliebig 61 Textdateien mit begrenzter Zeilenlaenge erzeugen kann.
62 langen Zeilen haben.
63 [ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17 62 [ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17
64 63
65 Neben dem Zeichen- bzw. Byte-Modus bietet cut noch den 64 Neben dem Zeichen- bzw. Byte-Modus bietet cut noch den
66 interessanteren Feld-Modus, den man mit `-f' einleitet. Mit ihm 65 Feld-Modus, den man mit `-f' einleitet. Mit ihm
67 koennen Felder ausgewaehlt werden. Das Trennzeichen (per 66 koennen Felder ausgewaehlt werden. Das Trennzeichen (per
68 Default der Tab) kann mit `-d' geaendert werden. 67 Default der Tab) kann mit `-d' geaendert werden.
69 68
70 Der typische Anwendungsfall fuer den Feld-Modus. Ist die 69 Der typische Anwendungsfall fuer cut im Feld-Modus ist die
71 Extraktion von Information aus der passwd-Datei. So z.B. der 70 Auswahl von Information aus der passwd-Datei. So z.B. der
72 Username, die User-ID und das Homeverzeichnis: 71 Benutername, seine ID und das Homeverzeichnis:
73 72
74 $ cut -d: -f1,3,6 /etc/passwd 73 $ cut -d: -f1,3,6 /etc/passwd
75 74
76 (Die Argumente fuer die Optionen koennen bei cut uebrigens 75 (Die Argumente fuer die Optionen koennen bei cut uebrigens
77 direkt angehaengt oder mit Whitespace abgetrennt folgen.) 76 mit Whitespace abgetrennt oder direkt angehaengt folgen.)
78 77
79 78
80 Dieser Feld-Modus ist fuer einfache tabellarische Dateien, 79 Dieser Feld-Modus ist fuer einfache tabellarische Dateien,
81 wie eben die passwd, gut geeignet. Er kommt aber schnell an 80 wie eben die passwd, gut geeignet. Er kommt aber schnell an
82 seine Grenzen. Gerade der uebliche Fall, dass an Whitespace 81 seine Grenzen. Gerade der uebliche Fall, dass an Whitespace
83 in Felder geteilt werden soll, wird damit nicht abgedeckt. 82 in Felder geteilt werden soll, wird damit nicht abgedeckt.
84 Der Delimiter kann nur genau ein Zeichen sein. Es kann also 83 Der Delimiter kann nur genau ein Zeichen sein. Es kann also
85 nicht sowohl an Leerzeichen als auch an Tabs getrennt werden. 84 nicht sowohl an Leerzeichen als auch an Tabs getrennt werden.
86 Auch unterteilt cut an jedem Trennzeichen. Zwei aneinander 85 Auch unterteilt cut an jedem Trennzeichen. Zwei aneinander
87 stehende Trennzeichen fuehren zu einem leeren Feld. Dieses 86 stehende Trennzeichen fuehren zu einem leeren Feld. Dieses
88 Verhalten widerspricht den Erwartungen fuer eine Datei mit 87 Verhalten widerspricht den Erwartungen, die man an die
89 Whitespace-getrennten Feldern. (Manche Implementierungen von 88 Verarbeitung einer Datei mit Whitespace-getrennten Feldern
90 cut, z.B. die von FreeBSD, haben deshalb Erweiterungen, die 89 hat. Manche Implementierungen von cut, z.B. die von FreeBSD,
91 das gewuenschte Verhalten fuer Whitespace-getrennte Felder 90 haben Erweiterungen, die das gewuenschte Verhalten fuer
92 bieten.) Ansonsten, d.h. wenn man portabel bleiben will, 91 Whitespace-getrennte Felder bieten. Ansonsten, d.h. wenn
93 hilft awk. 92 man portabel bleiben will, hilft awk.
94 93
95 Awk bietet noch eine weitere Funktion, die cut missen 94 Awk bietet noch eine weitere Funktion, die cut missen
96 laesst: Das Tauschen der Felder-Reihenfolge. Bei cut ist die 95 laesst: Das Tauschen der Feld-Reihenfolge in der Ausgabe. Bei
97 Reihenfolge der Feldauswahl irrelevant; ein Feld kann selbst 96 cut ist die Reihenfolge der Feldauswahlangabe irrelevant; ein
98 mehrfach angegeben werden. Der Aufruf von `cut -c 5-8,1,4-6' 97 Feld kann selbst mehrfach angegeben werden. So gibt der Aufruf
99 gibt z.B. die Zeichen Nummer 1, 4, 5, 6, 7 und 8 aus. Die 98 von `cut -c 5-8,1,4-6' die Zeichen Nummer 1, 4, 5, 6, 7 und 8
100 Auswahl aehnelt damit der Mengenlehre in der Mathematik: 99 in genau dieser Reihenfolge aus. Die Auswahl entspricht damit
101 Jedes angegebene Feld soll in der Ergebnismenge sein. Die 100 der Mengenlehre in der Mathematik: Jedes angegebene Feld wird
102 Felder der Ergebnismenge werden dabei immer in der gleichen 101 Teil der Ergebnismenge sein. Die Felder der Ergebnismenge sind
103 Reihenfolge ausgegeben wie sie in der Eingabe waren. 102 dabei immer gleich geordnet wie sie es in der Eingabe waren.
104 103 Oder, um die Worte der Manpage in Version 8 Unix
105 104 wiederzugeben: ``In data base parlance, it projects a relation.''
106 105 Cut fuehrt also die Datenbankoperation Projektion auf
107 cut(1) in Version 8 Unix 106 Textdateien aus. Die Wikipedia erklaert das in
108 ``In data base parlance, it projects a relation.'' 107 verstaendlicherer Sprache:
109
110 WP:
111 http://de.wikipedia.org/wiki/Projektion_(Informatik)#Projektion
112 108
113 Die Projektion entspricht der Projektionsabbildung aus der 109 Die Projektion entspricht der Projektionsabbildung aus der
114 Mengenlehre und kann auch Attributbeschränkung genannt 110 Mengenlehre und kann auch Attributbeschränkung genannt
115 werden. Sie extrahiert einzelne Attribute aus der 111 werden. Sie extrahiert einzelne Attribute aus der
116 ursprünglichen Attributmenge und ist somit als eine Art 112 ursprünglichen Attributmenge und ist somit als eine Art
117 Selektion auf Spaltenebene zu verstehen, das heißt, die 113 Selektion auf Spaltenebene zu verstehen, das heißt, die
118 Projektion blendet Spalten aus. 114 Projektion blendet Spalten aus.
119 115
116 [ http://de.wikipedia.org/wiki/Projektion_(Informatik)#Projektion
117
120 118
121 119
122 120
123 Geschichtliches 121 Geschichtliches
124 122
126 Licht der oeffentlichen Welt. Wenn man die Quellen von System 124 Licht der oeffentlichen Welt. Wenn man die Quellen von System
127 III durchforstet, findet man die Quellcodedatei cut.c mit dem 125 III durchforstet, findet man die Quellcodedatei cut.c mit dem
128 Zeitstempel 1980-04-11. 126 Zeitstempel 1980-04-11.
129 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd 127 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd
130 Das ist die aelteste Manifestation des Programms, die ich 128 Das ist die aelteste Manifestation des Programms, die ich
131 aufstoebern konnte. 129 aufstoebern konnte. Allerdings spricht die sccsid im
130 Quellcode von Version 1.5. Es muss also noch eine
131 Vorgeschichte geben. Zu dieser habe ich leider keinen Zugang
132 gefunden.
132 133
133 Aber werfen wir doch einen Blick auf die BSD-Linie: Dort ist mein 134 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 fruehester Fund ein cut.c mit dem Dateimodifikationsdatum
135 Spezialversion 4.3BSD-UWisc, 136 1986-11-07
137 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut
138 als Teil der Spezialversion 4.3BSD-UWisc,
136 [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix 139 [ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix
137 die im Januar 1987 veroeffentlicht wurde. 140 die im Januar 1987 veroeffentlicht wurde.
138 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut 141 Die Implementierung unterscheidet sich nur minimal von der
139 Die Datei unterscheidet sich nur minimal von der aus System III. 142 in System III.
140 Im bekannteren 4.3BSD-Tahoe (1988) taucht cut aber nicht auf. 143 Im bekannteren 4.3BSD-Tahoe (1988) taucht cut nicht auf.
141 Im darauf folgenden 4.3BSD-Reno (1990) gibt es wiederum ein 144 Das darauf folgende 4.3BSD-Reno (1990) liefert aber wieder
142 cut ... ein von Adam S. Moskowitz und Marciano Pitargue neu 145 ein cut mit aus. Dieses cut ist ein von Adam S. Moskowitz und
143 implementiertes cut, das 1989 in BSD aufgenommen wurde. 146 Marciano Pitargue neu implementiertes cut, das 1989 in BSD
147 aufgenommen wurde.
144 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut 148 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut
145 Seine Manpage 149 Seine Manpage
146 [ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1 150 [ 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. 151 erwaehnt bereits die erwartete Konformitaet mit POSIX.2.
148 Nun sollte man wissen, dass POSIX.2 erst im September 152 Nun sollte man wissen, dass POSIX.2 erst im September
149 1992 veroeffentlicht wurde, gut zwei Jahren *nachdem* die 153 1992 veroeffentlicht wurde, also gut zwei Jahren *nachdem* die
150 Manpage und das Programm geschrieben wurden. Dieses cut 154 Manpage und das Programm geschrieben wurden. Das Programm
151 wurde also anhand von Entwuerfen des Standards 155 wurde also anhand von Arbeitsversionen des Standards
152 implementiert. Zweieinhalb Jahre Arbeit war immerhin schon in 156 implementiert. Zweieinhalb Jahre Arbeit war immerhin schon in
153 den Standardisierungsprozess geflossen; bis zur 157 den Standardisierungsprozess geflossen; bis zur
154 Fertigstellung sollte es noch weitere zwei Jahre dauern. 158 Fertigstellung sollte es aber noch weitere zwei Jahre dauern.
155 159
156 Trotz all dieser Jahreszahlen aus den 80er Jahren gehoert cut 160 Trotz all dieser Jahreszahlen aus den 80er Jahren gehoert cut
157 aus Sicht des urspruenglichen Unix zu den juengeren Tools. 161 aus Sicht des urspruenglichen Unix zu den juengeren Tools.
158 Wenn cut auch ein Jahrzehnt aelter als Linux, der Kernel, ist, 162 Wenn cut auch ein Jahrzehnt aelter als Linux, der Kernel, ist,
159 so war Unix doch schon ueber zehn Jahre alt, als cut das 163 so war Unix doch schon ueber zehn Jahre alt, als cut das
160 erste Mal auftauchte. Insbesondere gehoerte cut noch nicht 164 erste Mal auftauchte. Insbesondere gehoerte cut noch nicht
161 zu Version 7 Unix, das die Ausgangsbasis aller modernen 165 zu Version 7 Unix, das die Ausgangsbasis aller modernen
162 Unix-Systeme darstellt. Die weit komplexeren Programme sed 166 Unix-Systeme darstellt. Die weit komplexeren Programme sed
163 und awk waren dort schon vertreten. Man muss sich also 167 und awk waren dort schon vertreten. Man muss sich also
164 fragen, warum cut ueberhaupt noch entwickelt wurde, wo es 168 fragen, warum cut ueberhaupt noch entwickelt wurde, wo es
165 schon zwei Programme gab, die die Aufgabe von cut bereits 169 schon zwei Programme gab, die die Aufgabe von cut abdeckten.
166 abdeckten. Ein Argument fuer cut ist seine Kompaktheit und 170 Ein Argument fuer cut war sicher seine Kompaktheit und
167 die damit verbundene Geschwindigkeit gegenueber dem damals 171 die damit verbundene Geschwindigkeit gegenueber dem damals
168 traegen awk. Diese schlanke Gestalt ist es auch, die der Unix 172 traegen awk. Diese schlanke Gestalt ist es auch, die der Unix
169 Philosopie entspricht: Mache eine Aufgabe und die richtig! 173 Philosopie entspricht: Mache eine Aufgabe und die richtig!
170 So bewaehrte sich cut. Es wurde in andere Unix Varianten 174 So bewaehrte sich cut. Es wurde in andere Unix Varianten
171 uebernommen, standardisiert und ist heutzutage ueberall 175 uebernommen, standardisiert und ist heutzutage ueberall
172 anzutreffen. 176 anzutreffen.
173 177
174 Die urspruengliche Variante (ohne -b) taucht schon 1985 in 178 Die urspruengliche Variante (ohne -b) tauchte schon 1985 in
175 der System V Interface Definition, einer wichtigen formalen 179 der System V Interface Definition, einer wichtigen formalen
176 Beschreibung von UNIX System V, und in allen relevanten 180 Beschreibung von UNIX System V, und in allen relevanten
177 Standards seither auf. Mit POSIX.2 im Jahre 1992 wurde cut 181 Standards seither auf. Mit POSIX.2 im Jahre 1992 wurde cut
178 zum ersten Mal in der heutigen Form (mit -b) standardisiert. 182 zum ersten Mal in der heutigen Form (mit -b) standardisiert.
183
184
185
186 Multibyte-Behandlung
187
188 Nun sind der Bytemodus und die damit verbundene
189 Multibyte-Verarbeitung des POSIX-Zeichenmodus bereits seit
190 1992 standardisiert, wie steht es aber mit deren Umsetzung?
191 Welche Versionen implementieren denn den POSIX korrekt?
192 Die Situation ist mehrschichtig. Es gibt traditionelle
193 Implementierungen, die nur -c und -f kennen. Dann gibt es
194 Implementierungen die zwar -b kennen, es aber nur als Alias
195 fuer -c handhaben. Diese Implementierungen funktionieren mit
196 Single-Byte-Encodings (z.B. US-ASCII, Latin1) korrekt, bei
197 Multi-Byte-Encodings (z.B. UTF-8) verhaelt sich ihr -c aber
198 wie -b (und -n wird ignoriert). Schliesslich gibt es noch
199 Implementierungen, die -b und -c tatsaechlich POSIX-konform
200 implementieren.
201
202 Traditionelle Zwei-Modi-Implementierungen sind z.B. die von
203 System III, System V und die aller BSDs bis in die 90er.
204
205 Pseude-Multibyte-Implementierungen bieten GNU und die
206 modernen NetBSDs und OpenBSDs. Wie sehr dort der Schein von
207 POSIX-konformitaet gewahrt wird, ist unterschiedlich. Nicht
208 immer findet man klare Aussagen wie diese:
209
210 /* Since we don't support multi-byte characters, the -c and -b
211 options are equivalent, and the -n option is meaningless. */
212
213 [ XXX
214
215 Tatsaechlich standardkonforme Implementierungen, die
216 Multibytes korrekt handhaben, bekommt man bei einem modernen
217 FreeBSD und bei den Heirloom Tools. Bei FreeBSD hat Tim Robbins
218 (tjr) im Sommer 2004 den Zeichenmodus POSIX-konform reimplementiert.
219 [ https://svnweb.freebsd.org/base?view=revision&revision=131194
220 Warum die beiden anderen grossen BSDs diese Aenderung nicht
221 uebernommen haben, bleibt offen. Es scheint aber an der im
222 obigen Kommentar formulierten Grundausrichtung zu liegen.
223
224 Wie findet man als Nutzer heraus, ob beim cut(1) des eigenen
225 Systems Multibytes korrekt unterstuetzt werden? Zuerst ist
226 entscheidend, ob das System selbst mit einem Multibyte-Encoding
227 arbeitet, denn tut es das nicht, dann entsprechen sich Zeichen
228 und Bytes und die Frage eruebrigt sich. Man kann dazu nachschauen,
229 welches Locale eingestellt ist, aber einfacher ist es, ein
230 typisches Mehrbytezeichen, wie z.B. einen Umlaut, auszugeben
231 und zu schauen ob dieses in einem oder in mehreren Bytes
232 kodiert ist:
233
234 $ echo ä | od -c
235 0000000 303 244 \n
236 0000003
237
238 In diesem Fall sind es zwei Bytes: oktal 303 und 244 . (Den
239 Zeilenumbruch fuegt echo(1) hinzu.)
240
241 Mit dem Programm iconv(1) kann man Test explizit in bestimmte
242 Kodierungen konvertieren. Hier Beispiele, wie das Ergebnis
243 bei Latin1 und wie es bei UTF-8 aussieht.
244
245 $ echo ä | iconv -t latin1 | od -c
246 0000000 344 \n
247 0000002
248
249 $ echo ä | iconv -t utf8 | od -c
250 0000000 303 244 \n
251 0000003
252
253 Die Ausgabe auf dem eigenen System (ohne die iconv-Konvertierung)
254 wird recht sicher einer dieser beiden Ausgaben entsprechen.
255
256 Nun zum Test der cut-Implementierung. Hat man ein UTF-8-System,
257 dann sollte sich eine POSIX-konforme Implementierung so verhalten:
258
259 $ echo aä | ./cut -c -2 | od -c
260 0000000 a 303 244 \n
261 0000004
262
263 $ echo aä | ./cut -b -2 | od -c
264 0000000 a 303 \n
265 0000003
266
267 $ echo aä | ./cut -b -2 -n | od -c
268 0000000 a \n
269 0000002
270
271 Bei einer Implementierung, die -b und -c gleich behandelt,
272 ist die Ausgabe in allen drei Faellen wie die mittlere: Es
273 werden die ersten beiden Bytes ausgegeben.
274
275
276
277 Implementierungen
278
279 Nun zum Blick auf den Code. Hier soll eine Auswahl an
280 Implementierungen etwas genauer betrachtet werden. Fuer einen
281 ersten Eindruck ist der Umfang des Quellcodes hilfreich.
282 Typischerweise steigt dieser ueber die Jahre an. Diese
283 Beobachtung kann hier in der Tendenz, aber nicht in jedem Fall,
284 bestaetigt werden.
285
286 Die Unterstuetzung des Byte-Modus (-b) erfordert zwangslaeufig
287 mehr Code, deshalb ist zu erwarten, dass diejenigen
288 Implementierungen, die ihn haben, umfangreicher sind.
289
290 Codevergleich
291
292 SLOC Zeilen Bytes Gehoert zu Dateidatum Kategorie
293 -----------------------------------------------------------------
294 116 123 2966 System III 1980-04-11 (trad)
295 118 125 3038 4.3BSD-UWisc 1986-11-07 (trad)
296 200 256 5715 4.3BSD-Reno 1990-06-25 (trad)
297 200 270 6545 NetBSD 1993-03-21 (trad)
298 218 290 6892 OpenBSD 2008-06-27 (pseudo)
299 224 296 6920 FreeBSD 1994-05-27 (trad)
300 232 306 7500 NetBSD 2014-02-03 (pseudo)
301 340 405 7423 Heirloom 2012-05-20 (POSIX)
302 382 586 14175 GNU coreutils 1992-11-08 (pseudo)
303 391 479 10961 FreeBSD 2012-11-24 (POSIX)
304 588 830 23167 GNU coreutils 2015-05-01 (pseudo)
305
306
307 $ awk -F' +' '{printf("%d\t%d (%.2f)\t%d (%.2f)\t%s\t%s\t%s\n",
308 $1, $2, $2/$1, $3, $3/$1, $4, $5, $6);}' <sloc
309 116 123 (1.06) 2966 (25.57) System III 1980-04-11 (trad)
310 118 125 (1.06) 3038 (25.75) 4.3BSD-UWisc 1986-11-07 (trad)
311 200 256 (1.28) 5715 (28.57) 4.3BSD-Reno 1990-06-25 (trad)
312 200 270 (1.35) 6545 (32.73) NetBSD 1993-03-21 (trad)
313 218 290 (1.33) 6892 (31.61) OpenBSD 2008-06-27 (pseudo)
314 224 296 (1.32) 6920 (30.89) FreeBSD 1994-05-27 (trad)
315 232 306 (1.32) 7500 (32.33) NetBSD 2014-02-03 (pseudo)
316 340 405 (1.19) 7423 (21.83) Heirloom 2012-05-20 (POSIX)
317 382 586 (1.53) 14175 (37.11) GNU coreutils 1992-11-08 (pseudo)
318 391 479 (1.23) 10961 (28.03) FreeBSD 2012-11-24 (POSIX)
319 588 830 (1.41) 23167 (39.40) GNU coreutils 2015-05-01 (pseudo)
320
321
322 Einige Auffaelligkeiten:
323
324 Das Kandidatenfeld teilt sich grob in vier Gruppen: Die zwei urspruenglichen
325 Implementierungen, die sich nur minimal unterscheiden, mit gut 100 SLOCs.
326 Dann die fuenf BSD-Versionen mit knapp ueber 200 SLOCs. Anschliessend die
327 zwei POSIX-konformen Programme und die alte GNU-Version mit 350-400
328 SLOCs. Und zum Abschluss die moderne GNU-Variante mit fast 600 SLOCs.
329
330 Die Abweichung von logischen Codezeilen (nach der Definition von
331 SLOCcount) und der Anzahl von Zeilenumbruechen in der Datei erstreckt
332 sich ueber einen Faktor von 1.06 bei den aeltesten Vertretern bis zu
333 Faktor 1.5 bei GNU.
334
335 Betrachtet man die Abweichungen zwischen den logischen Codezeilen und der
336 Dateigroesse, so pendelt das Teilnehmerfeld zwischen 25 und 30 Bytes je
337 Anweisung. Die Heirloom-Implementierung weicht nach unten ab, die
338 GNU-Implementierungen nach oben.
339
340
341
342 Das cut in System III von 1980 ist, wie man anhand der SCCS-ID erkennen
343 kann bereits in Version 1.5. Die Vorversionen konnte ich aber leider nicht
344 ermitteln.
345
346 Schaut man sich die SCCS-IDs in den BSD-Quellen an, dann findet man dort
347 Versionsnummern, die die Entwicklung dokumentieren:
348
349 4.3bsd-uwisc "@(#)cut.c 1.3";
350 4.3bsd-reno "@(#)cut.c 5.3 (Berkeley) 6/24/90";
351 netbsd "@(#)cut.c 5.4 (Berkeley) 10/30/90";
352 freebsd "@(#)cut.c 8.1 (Berkeley) 6/6/93";
353
354 Die neueren BSD-Versionen enthalten zwar weiterhin eine SCCS-ID, diese
355 ist aber bei Version "8.3 (Berkeley) 5/4/95" stehen geblieben. Danach
356 wurde scheinbar von SCCS auf CSV oder SVN gewechselt.
357
358 Bei GNU befindet sich folgender Copyright-Vermerk im Code:
359
360 Copyright (C) 1997-2015 Free Software Foundation, Inc.
361 Copyright (C) 1984 David M. Ihnat
362
363 Wie aus weiteren Kommentaren zu entnehmen ist, wurde der Code von zuerst
364 von David MacKenzie und spaeter von Jim Meyering ueberarbeitet. Letzterer
365 hat den Code 1992 auch ins Versionkontrollsystem eingestellt. Weshalb
366 die Jahre zwischen 1992 und 1997 nicht im Copyright-Vermerk auftauchen,
367 ist unklar.
368
369
179 370
180 371
181 Beschreibungen 372 Beschreibungen
182 373
183 Interessant ist ein Vergleich der Kurzbeschreibungen von cut, 374 Interessant ist ein Vergleich der Kurzbeschreibungen von cut,
200 FreeBSD 1.0 select portions of each line of a file 391 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 392 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 393 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 394 SunOS 5.5.1 cut out selected fields of each line of a file
204 395
396 Heirloom Tools cut out selected fields of each line of a file
397
205 POSIX cut out selected fields of each line of a file 398 POSIX cut out selected fields of each line of a file
206 399
207 GNU coreutils remove sections from each line of files 400 GNU coreutils remove sections from each line of files
208 401
209 Minix select out columns of a file 402 Minix select out columns of a file
238 bemueht ist, mit ``rearrange columns of data'' die 431 bemueht ist, mit ``rearrange columns of data'' die
239 unzutreffendste der Beschreibungen. 432 unzutreffendste der Beschreibungen.
240 433
241 434
242 435
243 Codevergleich
244
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
253
254 -b pseudo: openbsd, netbsd.2014, gnu*
255 -b real: freebsd.2014
256
257 :-& echo '123ä56' | cut -c -6 | od -c
258 0000000 1 2 3 303 244 5 \n
259 0000007
260
261 :-& echo '123ä56' | cut -b -6 | od -c
262 0000000 1 2 3 303 244 5 \n
263 0000007
264
265
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
278
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
292
293 (* == version hat -b)
294
295
296
297 system_iii.1980-04-11 Release 1.5
298
299 SCCSIDs:
300
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";
305
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";
308
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 $";
311
312 GNU
313 Copyright (C) 1997-2015 Free Software Foundation, Inc.
314 Copyright (C) 1984 David M. Ihnat
315 /* Written by David Ihnat. */
316
317 /* POSIX changes, bug fixes, long-named options, and cleanup
318 by David MacKenzie <djm@gnu.ai.mit.edu>.
319
320 Rewrite cut_fields and cut_bytes -- Jim Meyering. */
321
322 1992-11-08
323 Jim Meyering
324
325
326
327
328
329 436
330 Autoreninfo 437 Autoreninfo
331 438
332 Markus Schnalke interessiert sich fuer die Hintergruende 439 Markus Schnalke interessiert sich fuer die Hintergruende
333 von Unix und seinen Werkzeugen. Fuer die Erarbeitung dieses 440 von Unix und seinen Werkzeugen. Fuer die Erarbeitung dieses