meillo@26: .so macros meillo@26: .lc_ctype de_DE.utf8 meillo@26: meillo@26: .TL meillo@26: Cut out selected fields of each line of a file meillo@26: .AU meillo@26: markus schnalke meillo@26: .. meillo@26: .FS meillo@26: 2015-05. meillo@26: Dieser Text steht unter CC0. meillo@26: Er ist online verfügbar: meillo@26: .I http://marmaro.de/docs/ meillo@26: .FE meillo@26: meillo@26: .LP meillo@26: Cut ist ein klassisches Programm im Unix-Werkzeugkasten. meillo@26: In keinem ordentlichen Tutorial zur Shellprogrammierung fehlt meillo@26: es, denn es ist ein schönes, praktisches und anschauliches meillo@26: Helferlein. Hier soll ein wenig hinter seine Fassade geschaut meillo@26: werden. meillo@26: .SH meillo@26: Funktionsweise meillo@26: .LP meillo@26: Ursprünglich hatte cut zwei Modi, die später um einen dritten meillo@26: erweitert wurden. Cut schneidet entweder gewünschte Zeichen aus meillo@26: den Zeilen der Eingabe oder gewünschte, durch Trennzeichen meillo@26: definierte, Felder. meillo@26: .PP meillo@26: Der Zeichenmodus ist optimal geeignet um Festbreitenformate zu meillo@26: zerteilen. Man kann damit beispielsweise bestimmte meillo@26: Zugriffsrechte aus der Ausgabe von \f(CWls -l\fP ausschneiden, in meillo@26: diesem Beispiel die Rechte des Besitzers: meillo@26: .CS meillo@26: $ ls -l foo meillo@26: -rw-rw-r-- 1 meillo users 0 May 12 07:32 foo meillo@26: .sp .3 meillo@26: $ ls -l foo | cut -c 2-4 meillo@26: rw- meillo@26: .CE meillo@26: .LP meillo@26: Oder die Schreibrechte des Besitzers, der Gruppe und der meillo@26: Welt: meillo@26: .CS meillo@26: $ ls -l foo | cut -c 3,6,9 meillo@26: ww- meillo@26: .CE meillo@26: .LP meillo@26: Mit cut lassen sich aber auch Strings kürzen. meillo@26: .CS meillo@26: $ long=12345678901234567890 meillo@26: .sp .3 meillo@26: $ echo "$long" | cut -c -10 meillo@26: 1234567890 meillo@26: .CE meillo@26: .LP meillo@26: Dieser Befehl gibt die ersten maximal 10 Zeichen von meillo@26: \f(CW$long\fP aus. (Alternativ kann man hierfür \f(CWprintf meillo@26: "%.10s\\n" "$long"\fP verwenden.) meillo@26: .PP meillo@26: Geht es aber nicht um die Darstellung von Zeichen, sondern um meillo@26: ihre Speicherung, dann ist \f(CW-c\fP nur bedingt geeignet. meillo@26: Früher, als US-ASCII noch die omnipräsente Zeichenkodierung meillo@26: war, wurde jedes Zeichen mit genau einem meillo@26: Byte gespeichert. Somit selektierte \f(CWcut -c\fP gleichermaßen meillo@26: sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von meillo@26: Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von meillo@26: dieser Annahme lösen. In diesem Zug bekam cut mit meillo@26: POSIX.2-1992 einen Bytemodus (Option \f(CW-b\fP). Will man meillo@26: also nur die ersten maximal 500 Bytes vor dem meillo@26: Newline-Zeichen stehen haben (und den Rest stillschweigend meillo@26: ignorieren), dann macht man das mit: meillo@26: .CS meillo@26: $ cut -b -500 meillo@26: .CE meillo@26: .LP meillo@26: Den Rest kann man sich mit \f(CWcut -b 501-\fP einfangen. Diese meillo@26: Funktion ist insbesondere für POSIX wichtig, da man damit meillo@26: Textdateien mit begrenzter Zeilenlänge erzeugen kann meillo@26: .[[ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html#tag_20_28_17 . meillo@26: .PP meillo@26: Wenn auch der Bytemodus neu eingeführt worden war, so sollte meillo@26: er sich doch nur so verhalten wie der alte Zeichenmodus meillo@26: normalerweise schon implementiert war. Beim Zeichenmodus wurde meillo@26: dagegen eine neue Implementierungsweise gefordert. Das Problem meillo@26: war folglich nicht, den neuen Bytemodus zu implementieren, sondern meillo@26: den Zeichenmodus neu zu implementieren. meillo@26: .PP meillo@26: Neben dem Zeichen- und Bytemodus bietet cut noch den meillo@26: Feldmodus, den man mit \f(CW-f\fP einleitet. Mit ihm meillo@26: können Felder ausgewählt werden. Das Trennzeichen (per meillo@36: Default der Tab) kann mit \f(CW-d\fP ge\%ändert werden. Es gilt in meillo@26: gleicher Weise für die Eingabe und die Ausgabe. meillo@26: .PP meillo@26: Der typische Anwendungsfall für cut im Feldmodus ist die meillo@26: Auswahl von Information aus der passwd-Datei. Hier z.B. der meillo@26: Benutzername und seine ID: meillo@26: .CS meillo@26: $ cut -d: -f1,3 /etc/passwd meillo@26: root:0 meillo@26: bin:1 meillo@26: daemon:2 meillo@26: mail:8 meillo@26: ... meillo@26: .CE meillo@26: .LP meillo@26: (Die Argumente für die Optionen können bei cut übrigens meillo@26: sowohl mit Whitespace abgetrennt als auch direkt angehängt folgen.) meillo@26: .PP meillo@26: Dieser Feldmodus ist für einfache tabellarische Dateien, meillo@26: wie eben die passwd, gut geeignet. Er kommt aber schnell an meillo@26: seine Grenzen. Gerade der häufige Fall, dass an Whitespace meillo@26: in Felder geteilt werden soll, wird damit nicht abgedeckt. meillo@26: Der Delimiter kann bei cut nur genau ein Zeichen sein. Es kann meillo@26: demnach nicht sowohl an Leerzeichen als auch an Tabs aufgetrennt meillo@26: werden. Zudem unterteilt cut an jedem Trennzeichen. Zwei aneinander meillo@26: stehende Trennzeichen führen zu einem leeren Feld. Dieses meillo@26: Verhalten widerspricht den Erwartungen, die man an die meillo@26: Verarbeitung einer Datei mit Whitespace-getrennten Feldern meillo@26: hat. Manche Implementierungen von cut, z.B. die von FreeBSD, meillo@26: haben deshalb Erweiterungen, die das gewünschte Verhalten meillo@26: für Whitespace-getrennte Felder bieten. Ansonsten, d.h. wenn meillo@26: man portabel bleiben will, verwendet man awk in diesen meillo@26: Fällen. meillo@26: .PP meillo@26: Awk bietet noch eine weitere Funktion, die cut missen meillo@26: lässt: Das Tauschen der Feld-Reihenfolge in der Ausgabe. Bei meillo@26: cut ist die Reihenfolge der Feldauswahlangabe irrelevant; ein meillo@26: Feld kann selbst mehrfach angegeben werden. Dementsprechend gibt meillo@26: der Aufruf meillo@26: von \f(CWcut -c 5-8,1,4-6\fP die Zeichen Nummer 1, 4, 5, 6, 7 und 8 meillo@26: in genau dieser Reihenfolge aus. Die Auswahl entspricht damit meillo@26: der Mengenlehre in der Mathematik: Jedes angegebene Feld wird meillo@26: Teil der Ergebnismenge. Die Felder der Ergebnismenge sind meillo@26: hierbei immer gleich geordnet wie in der Eingabe. Um die Worte meillo@26: der Manpage von Version 8 Unix wiederzugeben: ``In data base meillo@26: parlance, it projects a relation.'' meillo@26: .[[ http://man.cat-v.org/unix_8th/1/cut meillo@26: Cut führt demnach die Datenbankoperation Projektion auf meillo@26: Textdateien aus. Die Wikipedia meillo@26: erklärt das folgendermaßen: meillo@26: .QP meillo@26: Die Projektion entspricht der Projektionsabbildung aus der meillo@26: Mengenlehre und kann auch Attributbeschränkung genannt meillo@26: werden. Sie extrahiert einzelne Attribute aus der meillo@26: ursprünglichen Attributmenge und ist somit als eine Art meillo@26: Selektion auf Spaltenebene zu verstehen, das heißt, die meillo@26: Projektion blendet Spalten aus. meillo@26: .[[ http://de.wikipedia.org/wiki/Projektion_(Informatik)#Projektion meillo@26: meillo@26: .SH meillo@26: Geschichtliches meillo@26: .LP meillo@26: Cut erblickte 1982 mit dem Release von UNIX System III das meillo@26: Licht der öffentlichen Welt. Wenn man die Quellen von System meillo@26: III durchforstet, findet man cut.c mit dem Zeitstempel 1980-04-11 meillo@26: .[[ http://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd . meillo@26: Das ist die älteste Implementierung des Programms, die ich meillo@26: aufstöbern konnte. Allerdings spricht die SCCS-ID im meillo@26: Quellcode von Version 1.5. Die Vorgeschichte liegt, der Vermutung meillo@26: Doug McIlroys meillo@26: .[[ http://minnie.tuhs.org/pipermail/tuhs/2015-May/004083.html meillo@26: zufolge, in PWB/UNIX, dessen Entwicklungslinie die Grundlage für meillo@26: System III war. In den von PWB 1.0 (1977) verfügbaren Quellen meillo@26: .[[ http://minnie.tuhs.org/Archive/PDP-11/Distributions/usdl/ meillo@26: ist cut noch nicht zu finden. Von PWB 2.0 scheinen keine meillo@26: Quellen oder hilf\%reiche Dokumentation verfügbar zu sein. meillo@26: PWB 3.0 wurde später aus Marketinggründen als System III meillo@26: bezeichnet und ist folglich mit ihm identisch. Eine Nebenlinie zu meillo@26: PWB war CB UNIX, das nur innerhalb meillo@26: der Bell Labs genutzt wurde. Das Handbuch von CB UNIX Edition 2.1 meillo@26: vom November 1979 enthält die früheste Erwähnung von cut, die meillo@26: meine Recherche zutage gefördert hat: eine Manpage für cut meillo@26: .[[ ftp://sunsite.icm.edu.pl/pub/unix/UnixArchive/PDP-11/Distributions/other/CB_Unix/cbunix_man1_02.pdf . meillo@26: .PP meillo@26: Nun ein Blick auf die BSD-Linie: Dort ist der früheste meillo@36: Fund ein cut.c mit dem Datei\%modifikationsdatum 1986-11-07 meillo@26: .[[ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-UWisc/src/usr.bin/cut meillo@26: als Teil der Spezialversion 4.3BSD-UWisc meillo@26: .[[ http://gunkies.org/wiki/4.3_BSD_NFS_Wisconsin_Unix , meillo@26: die im Januar 1987 veröffentlicht wurde. meillo@26: Die Implementierung unterscheidet sich nur minimal von der meillo@26: in System III. meillo@26: Im bekannteren 4.3BSD-Tahoe (1988) tauchte cut nicht auf. meillo@26: Das darauf folgende 4.3BSD-Reno (1990) lieferte aber wieder meillo@26: ein cut mit aus. Dieses cut war ein von Adam S. Moskowitz und meillo@26: Marciano Pitargue neu implementiertes cut, das 1989 in BSD meillo@26: aufgenommen wurde meillo@26: .[[ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut . meillo@26: Seine Manpage meillo@26: .[[ http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Reno/src/usr.bin/cut/cut.1 meillo@26: erwähnt bereits die erwartete Konformität mit POSIX.2. meillo@26: Nun muss man wissen, dass POSIX.2 erst im September meillo@26: 1992 veröffentlicht wurde, erst gut zwei Jahren nachdem die meillo@26: Manpage und das Programm geschrieben worden waren. Das Programm meillo@26: wurde folglich anhand von Arbeitsversionen des Standards meillo@26: implementiert. Ein Blick in den Code bekräftigt diese Vermutung. meillo@26: In der Funktion zum Parsen der Feldauswahlliste findet sich meillo@26: dieser Kommentar: meillo@26: .QP meillo@26: This parser is less restrictive than the Draft 9 POSIX spec. meillo@26: POSIX doesn't allow lists that aren't in increasing order or meillo@26: overlapping lists. meillo@26: .LP meillo@26: Im Draft 11.2 (1991-09) fordert POSIX diese Flexibilität bereits meillo@26: ein: meillo@26: .QP meillo@26: The elements in list can be repeated, can overlap, and can meillo@26: be specified in any order. meillo@26: .LP meillo@26: Zudem listet Draft 11.2 alle drei Modi, während in diesem meillo@26: BSD cut nur die zwei alten implementiert sind. Es könnte also meillo@26: sein, dass in Draft 9 der Bytemodus noch nicht vorhanden war. meillo@26: Ohne Zugang zu Draft 9 oder 10, war es leider nicht möglich, meillo@26: diese Vermutung zu prüfen. meillo@26: .PP meillo@26: Die Versionsnummern und Änderungsdaten der älteren meillo@26: BSD-Implementierungen kann man aus den SCCS-IDs, die vom meillo@26: damaligen Versionskontrollsystem in den Code eingefügt wurden, meillo@26: ablesen. So z.B. bei 4.3BSD-Reno: ``5.3 (Berkeley) 6/24/90''. meillo@26: .PP meillo@26: Das cut der GNU Coreutils enthält folgenden Copyrightvermerk: meillo@26: .CS meillo@26: Copyright (C) 1997-2015 Free Software Foundation, Inc. meillo@26: Copyright (C) 1984 David M. Ihnat meillo@26: .CE meillo@26: .LP meillo@26: Der Code hat also recht alte Ursprünge. Wie aus weiteren meillo@26: Kommentaren zu entnehmen ist, wurde der Programmcode zuerst von David meillo@26: MacKenzie und später von Jim Meyering überarbeitet. Letzterer meillo@26: hat den Code 1992 auch ins Versionkontrollsystem eingestellt. meillo@26: Weshalb die Jahre vor 1997, zumindest ab 1992, nicht im meillo@26: Copyright-Vermerk auftauchen, ist unklar. meillo@26: .PP meillo@26: Trotz der vielen Jahreszahlen aus den 80er Jahren gehört cut, meillo@26: aus Sicht des ursprünglichen Unix, zu den jüngeren Tools. meillo@26: Wenn cut auch ein Jahrzehnt älter als Linux, der Kernel, ist, meillo@26: so war Unix schon über zehn Jahre alt, als cut das meillo@26: erste Mal auftauchte. Insbesondere gehörte cut noch nicht meillo@26: zu Version 7 Unix, das die Ausgangsbasis aller modernen meillo@26: Unix-Systeme darstellt. Die weit komplexeren Programme sed meillo@26: und awk waren dort aber schon vertreten. Man muss sich also meillo@26: fragen, warum cut überhaupt noch entwickelt wurde, wo es meillo@26: schon zwei Programme gab, die die Funktion von cut abdecken meillo@26: konnten. Ein Argument für cut war sicher seine Kompaktheit und meillo@26: die damit verbundene Geschwindigkeit gegenüber dem damals meillo@26: trägen awk. Diese schlanke Gestalt ist es auch, die der meillo@26: Unix-Philosopie entspricht: Mache eine Aufgabe und die richtig! meillo@26: Cut überzeugte. Es wurde in andere Unix Varianten übernommen, meillo@26: stan\%dard\%isiert und ist heutzutage überall anzutreffen. meillo@26: .PP meillo@26: Die ursprüngliche Variante (ohne \f(CW-b\fP) wurde schon 1985 in meillo@26: der System V Interface Definition, einer wichtigen formalen meillo@26: Beschreibung von UNIX System V, spezifiziert und tauchte meillo@26: anschließend in allen relevanten Standards auf. Mit POSIX.2 meillo@26: im Jahre 1992 wurde cut zum ersten Mal in der heutigen Form meillo@26: (mit \f(CW-b\fP) standardisiert. meillo@26: meillo@36: .pl -1 meillo@26: .SH meillo@26: Multibyte-Unterstützung meillo@26: .LP meillo@26: Nun sind der Bytemodus und die damit verbundene meillo@26: Multibyte-Verarbeitung des POSIX-Zeichenmodus bereits seit meillo@26: 1992 standardisiert, wie steht es aber mit deren Umsetzung? meillo@26: Welche Versionen implementieren POSIX korrekt? meillo@26: Die Situation ist dreiteilig: Es gibt historische meillo@26: Implementierungen, die nur \f(CW-c\fP und \f(CW-f\fP kennen. Dann gibt es meillo@26: Implementierungen die \f(CW-b\fP zwar kennen, es aber lediglich als Alias meillo@36: für \f(CW-c\fP hand\%haben. Diese Implementierungen funktionieren mit meillo@26: Single-Byte-Encodings (z.B. US-ASCII, Latin1) korrekt, bei meillo@26: Multibyte-Encodings (z.B. UTF-8) verhält sich ihr \f(CW-c\fP aber meillo@26: wie \f(CW-b\fP (und \f(CW-n\fP wird ignoriert). Schließlich gibt es noch meillo@26: Implementierungen, die \f(CW-b\fP und \f(CW-c\fP tatsächlich POSIX-konform meillo@26: implementieren. meillo@26: .PP meillo@26: Historische Zwei-Modi-Implementierungen sind die von meillo@26: System III, System V und die aller BSDs bis in die 90er. meillo@26: .PP meillo@26: Pseudo-Multibyte-Implementierungen bieten GNU und die meillo@26: modernen NetBSDs und OpenBSDs. Man darf sich sicher fragen, meillo@26: ob dort ein Schein von POSIX-Konformität gewahrt wird. meillo@26: Teilweise findet man erst nach genauerer Suche heraus, dass meillo@26: \f(CW-c\fP und \f(CW-n\fP nicht wie erwartet funktionieren; teilweise machen es meillo@26: sich die Systeme auch einfach, indem sie auf meillo@26: Singlebyte-Zeichenkodierungen beharren, das aber dafür meillo@26: klar darlegen: meillo@26: .QP meillo@26: Since we don't support multi-byte characters, the \f(CW-c\fP and \f(CW-b\fP meillo@26: options are equivalent, and the \f(CW-n\fP option is meaningless. meillo@26: .[[ http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/cut/cut.c?rev=1.18&content-type=text/x-cvsweb-markup meillo@26: .LP meillo@26: Tatsächlich standardkonforme Implementierungen, die meillo@26: Multibytes korrekt handhaben, bekommt man bei einem modernen meillo@26: FreeBSD und bei den Heirloom Tools. Bei FreeBSD hat Tim Robbins meillo@26: im Sommer 2004 den Zeichenmodus POSIX-konform reimplementiert meillo@26: .[[ https://svnweb.freebsd.org/base?view=revision&revision=131194 . meillo@26: Warum die beiden anderen großen BSDs diese Änderung nicht meillo@26: übernommen haben, bleibt offen. Es scheint aber an der im meillo@26: obigen Kommentar formulierten Grundausrichtung zu liegen. meillo@26: .PP meillo@26: Wie findet man nun als Nutzer heraus, ob beim cut des eigenen meillo@26: Systems Multibytes korrekt unterstützt werden? Zuerst ist meillo@26: entscheidend, ob das System selbst mit einem Multibyte-Encoding meillo@26: arbeitet, denn tut es das nicht, dann entsprechen sich meillo@26: Zeichen und Bytes und die Frage erübrigt sich. Man kann das meillo@26: herausfinden indem man sich das Locale anschaut, aber einfacher meillo@26: ist es, ein typisches Mehrbytezeichen, wie z.B. einen Umlaut, meillo@26: auszugeben und zu schauen ob dieses in einem oder in mehreren meillo@26: Bytes kodiert ist: meillo@26: .CS meillo@26: $ echo ä | od -c meillo@26: 0000000 303 244 \\n meillo@26: 0000003 meillo@26: .CE meillo@26: .LP meillo@26: In diesem Fall sind es zwei Bytes: oktal 303 und 244. (Den meillo@26: Zeilenumbruch fügt echo hinzu.) meillo@26: .PP meillo@26: Mit dem Programm iconv kann man Text explizit in bestimmte meillo@26: Kodierungen konvertieren. Hier Beispiele, wie die Ausgabe meillo@26: bei Latin1 und wie sie bei UTF-8 aussieht: meillo@26: .CS meillo@26: $ echo ä | iconv -t latin1 | od -c meillo@26: 0000000 344 \\n meillo@26: 0000002 meillo@26: .sp .3 meillo@26: $ echo ä | iconv -t utf8 | od -c meillo@26: 0000000 303 244 \\n meillo@26: 0000003 meillo@26: .CE meillo@26: .LP meillo@26: Die Ausgabe auf dem eigenen System (ohne die iconv-Konvertierung) meillo@26: wird recht sicher einer dieser beiden Ausgaben entsprechen. meillo@26: .PP meillo@26: Nun zum Test der cut-Implementierung. Hat man ein UTF-8-System, meillo@26: dann sollte sich eine POSIX-konforme Implementierung folgendermaßen meillo@26: verhalten: meillo@26: .CS meillo@26: $ echo ä | cut -c 1 | od -c meillo@26: 0000000 303 244 \\n meillo@26: 0000003 meillo@26: .sp .3 meillo@26: $ echo ä | cut -b 1 | od -c meillo@26: 0000000 303 \\n meillo@26: 0000002 meillo@26: .sp .3 meillo@26: $ echo ä | cut -b 1 -n | od -c meillo@26: 0000000 \\n meillo@26: 0000001 meillo@26: .CE meillo@26: .LP meillo@26: Bei einer Pseudo-POSIX-Implementierung ist die Ausgabe in meillo@26: allen drei Fällen wie die mittlere: Es wird das erste Byte meillo@26: ausgegeben. meillo@26: meillo@36: .pl +1 meillo@26: .SH meillo@26: Implementierungen meillo@26: .LP meillo@26: Nun ein Blick auf den Code. Betrachtet wird eine Auswahl an meillo@26: Implementierungen. meillo@26: .PP meillo@26: Für einen ersten Eindruck ist der Umfang des Quellcodes meillo@26: hilfreich. Typischerweise steigt dieser über die Jahre an. Diese meillo@26: Beobachtung kann hier in der Tendenz, aber nicht in jedem Fall, meillo@26: bestätigt werden. Die POSIX-konforme Umsetzung des Zeichenmodus meillo@26: erfordert zwangsläufig mehr Code, deshalb sind diese meillo@26: Implementierungen tendenziell umfangreicher. meillo@26: .TS meillo@26: center; meillo@26: r r r l l l. meillo@26: SLOC Zeilen Bytes Gehört zu Dateidatum Kategorie meillo@26: _ meillo@26: 116 123 2966 System III 1980-04-11 historisch meillo@26: 118 125 3038 4.3BSD-UWisc 1986-11-07 historisch meillo@26: 200 256 5715 4.3BSD-Reno 1990-06-25 historisch meillo@26: 200 270 6545 NetBSD 1993-03-21 historisch meillo@26: 218 290 6892 OpenBSD 2008-06-27 pseudo-POSIX meillo@26: 224 296 6920 FreeBSD 1994-05-27 historisch meillo@26: 232 306 7500 NetBSD 2014-02-03 pseudo-POSIX meillo@26: 340 405 7423 Heirloom 2012-05-20 POSIX meillo@26: 382 586 14175 GNU coreutils 1992-11-08 pseudo-POSIX meillo@26: 391 479 10961 FreeBSD 2012-11-24 POSIX meillo@26: 588 830 23167 GNU coreutils 2015-05-01 pseudo-POSIX meillo@26: .TE meillo@26: .LP meillo@26: Das Kandidatenfeld teilt sich grob in vier Gruppen: (1) Die zwei meillo@26: ursprünglichen Implementierungen, die sich nur minimal meillo@26: unterscheiden, mit gut 100 SLOCs. (2) Die fünf BSD-Versionen mit meillo@26: gut 200 SLOCs. (3) Die zwei POSIX-konformen Programme und meillo@26: die alte GNU-Version mit 340\(en390 SLOCs. Und schließlich (4) die meillo@26: moderne GNU-Variante mit fast 600 SLOCs. meillo@26: .PP meillo@26: Die Abweichung zwischen logischen Codezeilen (SLOC, ermittelt mit meillo@26: SLOCcount) und der Anzahl von Zeilenumbrüchen in der Datei (\f(CWwc meillo@26: -l\fP) erstreckt sich über eine Spanne von Faktor 1,06 bei den meillo@26: ältesten Vertretern bis zu Faktor 1,5 bei GNU. Den größten meillo@26: Einfluss darauf haben Leerzeilen, reine Kommentarzeilen und meillo@26: die Größe des Lizenzblocks am Dateianfang. meillo@26: .PP meillo@26: Betrachtet man die Abweichungen zwischen den logischen Codezeilen meillo@26: und der Dateigröße (\f(CWwc -c\fP), so pendelt das Teilnehmerfeld meillo@26: zwischen 25 und 30 Bytes je Anweisung. Die Heirloom-Implementierung meillo@26: weicht mit nur 21 nach unten ab, die GNU-Implementierungen mit meillo@26: fast 40 nach oben. Bei GNU liegt dies hauptsächlich an deren meillo@26: Programmierstil, mit spezieller Einrückung und langen Bezeichnern. meillo@26: Ob man die Heirloom-Implementierung meillo@26: .[[ http://heirloom.cvs.sourceforge.net/viewvc/heirloom/heirloom/cut/cut.c?revision=1.6&view=markup meillo@26: als besonders kryptisch meillo@26: oder als besonders elegant bezeichnen will, das soll der meillo@26: eigenen Einschätzung des Lesers überlassen bleiben. Vor allem meillo@26: der Vergleich mit einer GNU-Implementierung meillo@26: .[[ http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/cut.c;hb=e981643 meillo@26: ist eindrucksvoll. meillo@26: .PP meillo@26: Die interne Struktur der Programmcodes (in C) ist meist ähnlich. meillo@26: Neben der obligatorischen main-Funktion, die die Kommandozeilenargumente meillo@26: verarbeitet, gibt es im Normalfall eine Funktion, die die meillo@26: Feldauswahl in eine interne Datenstruktur überführt. Desweiteren meillo@26: haben fast alle Implementierungen separate Funktionen für jeden meillo@26: ihrer Modi. Bei den POSIX-konformen Implementierungen meillo@26: wird die \f(CW-b -n\fP-Kombination als weiterer Modus behandelt, und meillo@26: damit in einer eigenen Funktion umgesetzt. Nur bei der frühen meillo@26: System III-Implementierung (und seiner 4.3BSD-UWisc-Variante) meillo@26: wird außer den Fehlerausgaben alles in der main-Funktion meillo@26: erledigt. meillo@26: .PP meillo@26: Cut-Implementierungen haben typischerweise zwei limitierende meillo@26: Größen: Die Maximalanzahl unterstützter Felder und die maximale meillo@26: Zeilenlänge. Bei System III sind beide Größen auf 512 begrenzt. meillo@26: 4.3BSD-Reno und die BSDs der 90er Jahre haben ebenfalls fixe meillo@26: Grenzen (\f(CW_BSD_LINE_MAX\fP bzw. \f(CW_POSIX2_LINE_MAX\fP). Bei modernen meillo@26: FreeBSDs, NetBSDs, bei allen GNU-Implementierungen und bei meillo@26: Heirloom kann sowohl die Felderanzahl als auch die maximale meillo@26: Zeilenlänge beliebig groß werden; der Speicher dafür wird meillo@26: dynamisch alloziiert. OpenBSD ist ein Hybrid aus fixer meillo@26: Maximalzahl an Feldern und beliebiger Zeilenlänge. Die meillo@26: begrenzte Felderanzahl scheint jedoch kein Praxisproblem meillo@26: darzustellen, da \f(CW_POSIX2_LINE_MAX\fP mit mindestens 2048 durchaus meillo@26: groß genug sein sollte. meillo@26: meillo@26: .SH meillo@26: Beschreibungen meillo@26: .LP meillo@26: Interessant ist zudem ein Vergleich der Kurzbeschreibungen von meillo@26: cut, wie sie sich in der Titelzeile der Manpages oder manchmal meillo@26: am Anfang der Quellcodedatei finden. Die folgende Liste meillo@26: ist grob zeitlich geordnet und nach Abstammung gruppiert: meillo@26: .TS meillo@26: center; meillo@26: l l. meillo@26: CB UNIX cut out selected fields of each line of a file meillo@26: System III cut out selected fields of each line of a file meillo@26: System III \(dg cut and paste columns of a table (projection of a relation) meillo@26: System V cut out selected fields of each line of a file meillo@26: HP-UX cut out (extract) selected fields of each line of a file meillo@26: .sp .3 meillo@26: 4.3BSD-UWisc \(dg cut and paste columns of a table (projection of a relation) meillo@26: 4.3BSD-Reno select portions of each line of a file meillo@26: NetBSD select portions of each line of a file meillo@26: OpenBSD 4.6 select portions of each line of a file meillo@26: FreeBSD 1.0 select portions of each line of a file meillo@26: FreeBSD 10.0 cut out selected portions of each line of a file meillo@26: SunOS 4.1.3 remove selected fields from each line of a file meillo@26: SunOS 5.5.1 cut out selected fields of each line of a file meillo@26: .sp .3 meillo@26: Heirloom Tools cut out selected fields of each line of a file meillo@26: Heirloom Tools \(dg cut out fields of lines of files meillo@26: .sp .3 meillo@26: GNU coreutils remove sections from each line of files meillo@26: .sp .3 meillo@26: Minix select out columns of a file meillo@26: .sp .3 meillo@26: Version 8 Unix rearrange columns of data meillo@26: ``Unix Reader'' rearrange columns of text meillo@26: .sp .3 meillo@26: POSIX cut out selected fields of each line of a file meillo@26: .TE meillo@26: .LP meillo@26: Die mit `\(dg' markierten Beschreibungen sind aus dem meillo@26: jeweiligen Quellcode entnommen. Der POSIX-Eintrag enthält meillo@26: die Beschreibung im Standard. Der ``Unix Reader'' ist ein meillo@26: rückblickendes Textdokument von Doug McIlroy, das das meillo@26: Auftreten der Tools in der Geschichte des Research Unix zum meillo@26: Thema hat meillo@26: .[[ http://doc.cat-v.org/unix/unix-reader/contents.pdf . meillo@26: Eigentlich sollte seine Beschreibung der in Version 8 Unix meillo@26: entsprechen. Die Abweichung könnte ein Übertragungsfehler meillo@26: oder eine nachträgliche Korrektur sein. Alle übrigen meillo@26: Beschreibungen entstammen den Manpages. meillo@26: .PP meillo@26: Oft ist mit der Zeit die POSIX-Beschreibung übernommen meillo@26: oder an sie angeglichen worden, wie beispielsweise bei FreeBSD meillo@26: .[[ https://svnweb.freebsd.org/base?view=revision&revision=167101 . meillo@26: .PP meillo@26: Interessant ist, dass die GNU coreutils seit Anbeginn vom meillo@26: Entfernen von Teilen der Eingabe sprechen, wohingegen die meillo@26: Kommandozeilenangabe klar ein Auswählen darstellt. Die meillo@26: Worte ``cut out'' sind vielleicht auch zu missverständlich. meillo@26: HP-UX hat sie deshalb präzisiert. meillo@26: .PP meillo@26: Beim Begriff, was selektiert wird, ist man sich ebenfalls meillo@26: uneins. Die Einen reden von Feldern (POSIX), Andere von meillo@26: Abschnitten bzw. Teilen (BSD) und wieder Andere von Spalten meillo@26: (Research Unix). meillo@26: .PP meillo@26: Die scheinbar unzutreffende Beschreibung meillo@26: bei Version 8 Unix (``rearrange columns of data'') ist meillo@26: dadurch zu erklären, dass die Manpage sowohl cut als auch meillo@26: paste abdeckt. In ihrer Kombination können tatsächlich meillo@26: Spalten umgeordnet werden. meillo@26: meillo@26: .SH meillo@26: Referenzen meillo@26: .LP meillo@26: .nf meillo@26: ._r meillo@26: