Bash
Der Befehl zum Ausschneiden
Suche…
Einführung
Der Befehl cut
ist eine schnelle Methode zum Extrahieren von Teilen von Textzeilen. Es gehört zu den ältesten Unix-Befehlen. Die beliebtesten Implementierungen sind die GNU-Version unter Linux und die FreeBSD-Version unter MacOS. Jede Unix-Variante hat jedoch ihre eigene. Siehe unten für Unterschiede. Die Eingabezeilen werden entweder aus stdin
oder aus Dateien gelesen, die als Argumente in der Befehlszeile aufgeführt sind.
Syntax
schneiden -f1,3 # Extrakt ersten und dritten getabulatortrennte Feld (von stdin)
cut -f1-3 # Auszug aus dem ersten bis dritten Feld (Enden eingeschlossen)
cut -f-3 # -3 wird als 1-3 interpretiert
cut -f2- # 2- wird vom zweiten bis zum letzten interpretiert
Schneiden Sie -c1-5,10 # aus stdin die Zeichen an den Positionen 1,2,3,4,5,10 aus
cut -s -f1 # unterdrückt Zeilen, die keine Trennzeichen enthalten
cut --complement -f3 # (nur GNU-Cut) extrahiert alle Felder außer dem dritten
Parameter
Parameter | Einzelheiten |
---|---|
-f, --fields | Feldbasierte Auswahl |
-d, --delimiter | Trennzeichen für feldbasierte Auswahl |
-c, --Zeichen | Zeichenbasierte Auswahl, Trennzeichen ignoriert oder Fehler |
-s, - nur begrenzt | Zeilen ohne Trennzeichen unterdrücken (sonst wie gedruckt) |
--ergänzen | Invertierte Auswahl (alle außer den angegebenen Feldern / Zeichen extrahieren) |
- Ausgabenbegrenzer | Geben Sie an, wann es sich vom Eingangsbegrenzer unterscheiden muss |
Bemerkungen
1. Syntaxunterschiede
Lange Optionen in der obigen Tabelle werden nur von der GNU-Version unterstützt.
2. Kein Charakter wird speziell behandelt
Der FreeBSD- cut
(der zum Beispiel mit MacOS --complement
) verfügt nicht über den Schalter --complement
Zeichenbereichen kann stattdessen der Befehl colrm
verwendet werden:
$ cut --complement -c3-5 <<<"123456789"
126789
$ colrm 3 5 <<<"123456789"
126789
Es gibt jedoch einen großen Unterschied, da TAB-Zeichen (ASCII 9) in colrm
bis zum nächsten Vielfachen von acht als reelle colrm
und als (-1) breite colrm
(ASCII 8) behandelt werden. Im Gegensatz dazu behandelt cut
alle Zeichen als eine Spalte.
$ colrm 3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
12ABCDEF
$ cut --complement -c3-8 <<<$'12\tABCDEF'
12F
3. (Noch immer keine) Internationalisierung
Als der cut
entworfen wurde, waren alle Zeichen ein Byte lang und die Internationalisierung war kein Problem. Als Schreibsysteme mit breiteren Zeichen populär wurden, bestand die von POSIX angenommene Lösung darin, zwischen dem alten -c
Schalter zu wechseln, der seine Bedeutung für die Auswahl von Zeichen beibehalten sollte , unabhängig davon, wie viele Bytes breit sind, und einen neuen Schalter -b
einzuführen, der sollte select bytes, unabhängig von der aktuellen Zeichenkodierung. In den meisten gängigen Implementierungen wurde -b
eingeführt und funktioniert, aber -c
funktioniert immer noch genauso wie -b
und nicht wie es sollte. Zum Beispiel mit GNU- cut
:
Es scheint, dass der Spam-Filter von SE schwarze Texte mit isolierten Kanji-Zeichen in die schwarze Liste einfügt. Ich konnte diese Einschränkung nicht überwinden, daher sind die folgenden Beispiele weniger ausdrucksvoll als sie sein könnten.
# In an encoding where each character in the input string is three bytes wide,
# Selecting bytes 1-6 yields the first two characters (correct)
$ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
...first two characters of each line...
# Selecting all three characters with the -c switch doesn’t work.
# It behaves like -b, contrary to documentation.
$ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
...first character of each line...
# In this case, an illegal UTF-8 string is produced.
# The -n switch would prevent this, if implemented.
$ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
...second byte, which is an illegal UTF-8 sequence...
Wenn sich Ihre Zeichen außerhalb des ASCII-Bereichs befinden und Sie cut
möchten, sollten Sie immer die Zeichenbreite in Ihrer Kodierung -b
und -b
entsprechend verwenden. Wenn -c
beginnt, wie dokumentiert zu arbeiten, müssen Sie Ihre Skripts nicht ändern.
4. Geschwindigkeitsvergleiche
Die Grenzen von cut
haben Zweifel an der Nützlichkeit. In der Tat kann dieselbe Funktionalität durch leistungsfähigere, populärere Dienstprogramme erreicht werden. Der Vorteil von cut
ist jedoch seine Leistung . Nachfolgend finden Sie einige Geschwindigkeitsvergleiche. test.txt
hat drei Millionen Zeilen mit jeweils fünf durch Leerzeichen getrennten Feldern. Für den awk
Test wurde mawk
verwendet, weil es schneller als GNU awk
. Die Hülle selbst (letzte Zeile) ist bei weitem die schlechteste Leistung. Die angegebenen Zeiten (in Sekunden), was die time
Befehl als Echtzeit gibt.
(Nur um Missverständnisse zu vermeiden: Alle getesteten Befehle gaben dieselbe Ausgabe mit der angegebenen Eingabe aus, sind jedoch natürlich nicht gleichwertig und würden in verschiedenen Situationen unterschiedliche Ausgaben ergeben, insbesondere wenn die Felder durch eine variable Anzahl von Leerzeichen begrenzt sind.
Befehl | Zeit |
---|---|
cut -d ' ' -f1,2 test.txt | 1,138s |
awk '{print $1 $2}' test.txt | 1.688s |
join -a1 -o1.1,1.2 test.txt /dev/null | 1,767 s |
perl -lane 'print "@F[1,2]"' test.txt | 11.390s |
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt | 22,925s |
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt | 52.122s |
while read ab _; do echo $a $b; done <test.txt | 55,582 s |
5. Referenzseiten
Grundlegende Verwendung
Die typische Verwendung erfolgt bei CSV-Dateien, wobei jede Zeile aus Feldern besteht, die durch ein Trennzeichen getrennt sind, das durch die Option -d
angegeben wird. Das Standardbegrenzer ist das TAB-Zeichen. Angenommen, Sie haben eine data.txt
mit Zeilen wie
0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367
Dann
# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644
# extract the second dot-delimited field
$ cut -d. -f2 data.txt
8024
3205
2367
# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt
948.80
056222
943831
Wie üblich können zwischen einem Switch und seinem Parameter optionale Leerzeichen stehen: -d,
-d ,
GNU- cut
ermöglicht die Angabe einer Option --output-delimiter
: (Ein unabhängiges Merkmal dieses Beispiels ist, dass ein Semikolon als Eingabebegrenzer mit --output-delimiter
werden muss, um eine besondere Behandlung durch die Shell zu vermeiden.
$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b
Nur ein Trennzeichen
Sie können nicht mehr als ein Trennzeichen haben: Wenn Sie etwas wie -d ",;:"
angeben, verwenden einige Implementierungen nur das erste Zeichen als Trennzeichen (in diesem Fall das Komma). Andere Implementierungen (z. B. GNU- cut
) geben den Wert an Ihnen eine Fehlermeldung.
$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.
Wiederholte Trennzeichen werden als leere Felder interpretiert
$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b
ist ziemlich offensichtlich, aber mit raumbegrenzten Zeichenketten ist es für einige weniger offensichtlich
$ cut -d ' ' -f1,3 <<<"a b c d e"
a b
cut
kann nicht wie in der Shell und anderen Programmen Argumente analysiert werden.
Kein Zitat
Es gibt keine Möglichkeit, den Begrenzer zu schützen. Tabellenkalkulationen und ähnliche CSV-Handhabungssoftware können in der Regel ein Anführungszeichen erkennen, mit dem Zeichenfolgen definiert werden können, die ein Trennzeichen enthalten. Mit dem cut
kannst du nicht.
$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1
Extrahieren, nicht manipulieren
Sie können nur Teile von Zeilen extrahieren, keine Felder neu anordnen oder wiederholen.
$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith