Login
Newsletter
Werbung

Do, 23. Juli 2015, 15:00

»cut out selected fields of each line of a file«

Die Geschichte des Programms »cut« in Unix

Ein klassisches Programm im Unix-Werkzeugkasten ist cut. In keinem ordentlichen Tutorial zur Shellprogrammierung fehlt es, denn es ist ein schönes, praktisches und anschauliches Helferlein. Hier soll ein wenig hinter seine Fassade geschaut werden.

Funktionsweise

Ursprünglich hatte cut zwei Modi, die später um einen dritten erweitert wurden. cut schneidet entweder gewünschte Zeichen aus den Zeilen der Eingabe oder gewünschte, durch Trennzeichen definierte, Felder.

Der Zeichenmodus ist optimal geeignet, um Festbreitenformate zu zerteilen. Man kann damit beispielsweise bestimmte Zugriffsrechte aus der Ausgabe von ls -l ausschneiden, in diesem Beispiel die Rechte des Besitzers:

$ ls -l foo
-rw-rw-r-- 1 meillo users 0 May 12 07:32 foo
$ ls -l foo | cut -c 2-4
rw-

Oder die Schreibrechte des Besitzers, der Gruppe und der Welt:

$ ls -l | cut -c 3,6,9
ww-

Mit cut lassen sich aber auch Strings kürzen:

$ long=12345678901234567890
$ echo "$long" | cut -c -10
1234567890

Dieser Befehl gibt die ersten maximal 10 Zeichen von $long aus. (Alternativ kann man hierfür printf "%.10s\n" "$long" verwenden.)

Geht es aber nicht um die Darstellung von Zeichen, sondern um ihre Speicherung, dann ist -c nicht unbedingt geeignet. Früher, als US-ASCII noch die omnipräsente Zeichenkodierung war, wurde jedes Zeichen mit genau einem Byte gespeichert. Somit selektierte cut -c gleichermaßen sowohl Ausgabezeichen als auch Bytes. Mit dem Aufkommen von Multibyte-Kodierungen (wie UTF-8) musste man sich jedoch von dieser Annahme lösen. In diesem Zug bekam cut mit POSIX.2-1992 einen Bytemodus (Option -b). Will man also nur die ersten maximal 500 Bytes vor dem Newline-Zeichen stehen haben (und den Rest stillschweigend ignorieren), dann macht man das mit:

$ cut -b -500

Den Rest kann man sich mit cut -b 501- einfangen. Diese Funktion ist insbesondere für POSIX wichtig, da man damit Textdateien mit begrenzter Zeilenlänge erzeugen kann.

Wenn auch der Bytemodus neu eingeführt worden war, so sollte er sich doch nur so verhalten wie der alte Zeichenmodus normalerweise schon implementiert war. Beim Zeichenmodus aber wurde eine neue Implementierungsweise gefordert. Das Problem war folglich nicht, den neuen Bytemodus zu implementieren, sondern den Zeichenmodus neu zu implementieren.

Neben dem Zeichen- und Bytemodus bietet cut noch den Feldmodus, den man mit -f einleitet. Mit ihm ist es möglich, Felder auszuwählen. Das Trennzeichen (per Default der Tab) kann mit -d geändert werden. Es gilt in gleicher Weise für die Eingabe und die Ausgabe.

Der typische Anwendungsfall für cut im Feldmodus ist die Auswahl von Information aus der passwd-Datei. Hier z.B. der Benutzername und seine ID:

$ cut -d: -f1,3 /etc/passwd
root:0
bin:1
daemon:2
mail:8
...

Die einzelnen Argumente für die Optionen können bei cut übrigens sowohl mit Whitespace abgetrennt (wie oben zu sehen) als auch direkt angehängt folgen.

Dieser Feldmodus ist für einfache tabellarische Dateien, wie eben die passwd-Datei, gut geeignet. Er kommt aber schnell an seine Grenzen. Gerade der häufige Fall, dass an Whitespace in Felder geteilt werden soll, wird damit nicht abgedeckt. Der Delimiter kann bei cut nur genau ein Zeichen sein. Es kann demnach nicht sowohl an Leerzeichen als auch an Tabs aufgetrennt werden. Zudem unterteilt cut an jedem Trennzeichen. Zwei aneinander stehende Trennzeichen führen zu einem leeren Feld. Dieses Verhalten widerspricht den Erwartungen, die man an die Verarbeitung einer Datei mit Whitespace-getrennten Feldern hat. Manche Implementierungen von cut, z.B. die von FreeBSD, haben deshalb Erweiterungen, die das gewünschte Verhalten für Whitespace-getrennte Felder bieten. Ansonsten, d.h. wenn man portabel bleiben will, verwendet man awk in diesen Fällen.

awk bietet noch eine weitere Funktion, die cut missen lässt: Das Tauschen der Feld-Reihenfolge in der Ausgabe. Bei cut ist die Reihenfolge der Feldauswahlangabe irrelevant; ein Feld kann selbst mehrfach angegeben werden. Dementsprechend gibt der Aufruf von cut -c 5-8,1,4-6 die Zeichen Nummer 1, 4, 5, 6, 7 und 8 in genau dieser Reihenfolge aus. Die Auswahl entspricht damit der Mengenlehre in der Mathematik: Jedes angegebene Feld wird Teil der Ergebnismenge. Die Felder der Ergebnismenge sind hierbei immer gleich geordnet wie in der Eingabe. Um die Worte der Manpage von Version 8 Unix wiederzugeben: »In data base parlance, it projects a relation.« cut führt demnach die Datenbankoperation Projektion auf Textdateien aus. Die Wikipedia erklärt das folgendermaßen:

»Die Projektion entspricht der Projektionsabbildung aus der Mengenlehre und kann auch Attributbeschränkung genannt werden. Sie extrahiert einzelne Attribute aus der ursprünglichen Attributmenge und ist somit als eine Art Selektion auf Spaltenebene zu verstehen, das heißt, die Projektion blendet Spalten aus.«

Kommentare (Insgesamt: 8 || Alle anzeigen )
Danke (Ich, Sa, 25. Juli 2015)
Re: Noch nie davon gehört (IckeDetteKiekeMal, Fr, 24. Juli 2015)
Re[2]: Noch nie davon gehört (alter Sack im Jungbrunnen, Fr, 24. Juli 2015)
Re[2]: Noch nie davon gehört (dede, Fr, 24. Juli 2015)
Re: Noch nie davon gehört (Alfred Halbstadt, Fr, 24. Juli 2015)
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung