Es gibt zwei grundlegende Ansätze, die beim Umgang mit Feldern verwendet werden können: i) Verwenden eines Tools, das Felder versteht; ii) Verwenden Sie einen regulären Ausdruck. Von den beiden ist der erstere normalerweise sowohl robuster als auch einfacher.
Viele der allgemein verfügbaren Tools auf * nix sind entweder explizit für den Umgang mit Feldern konzipiert oder verfügen über raffinierte Tricks, um dies zu vereinfachen.
1. Verwenden Sie ein Tool, das Felder versteht
1,1 awk
Das klassische Werkzeug hier ist awk
. Es wird automatisch jede Eingangsleitung in Felder aufgeteilt (die Feldtrennstandardmäßig Leerzeichen sondern kann mit der ändernden -F
Flag) und die Felder sind dann an das awk
Skript als wo die Feldnummer. Das erste Feld ist , das zweite usw.$n
n
$1
$2
Drucken Sie Zeilen, deren 3. Feld ist foo
.
awk '$3=="foo"' file
Ändern des Trennzeichens in :
awk -F":" '$3=="foo"' file
Die Standardaktion von awk
ist das Drucken. Daher drucken die obigen Befehle alle Zeilen, deren 3. Feld ist foo
. Bei der Verwendung -F
können Sie beliebige Feldtrennzeichen festlegen und sogar reguläre Ausdrücke verwenden.
Wie kann ich nur Zeilen drucken, deren 3. Feld nicht ist foo
?
awk '$3!="foo"' file
Wie kann ich nur Zeilen drucken, deren 3. Feld übereinstimmt foo
?
Wenn Sie nur nach Feldern suchen, die einem Muster entsprechen (z. B. foo
Übereinstimmungen foobar
), verwenden Sie ~
anstelle von ==
:
awk '$3~/foo/' file
Wie kann ich nur Zeilen drucken, deren 3. Feld nicht übereinstimmt foo
?
awk '$3!~/foo/' file
Wie kann ich das 3. Feld ändern foo
?
awk '$3="foo"' file
1,2 Perl
Eine andere Wahl ist perl
Einzeiler. Wie awk ist Perl eine voll funktionsfähige Skriptsprache, kann aber auch als Befehlszeilenprogramm ausgeführt werden, das ein Skript als Eingabe verwendet. Sein Verhalten wird durch Befehlszeilenschalter geändert, von denen die relevantesten für diese Frage sind:
-e
: das Skript, das ausgeführt werden perl
soll;
-n
: Lesen Sie die Eingabedatei Zeile für Zeile;
-p
: drucke jede Eingabezeile nach dem Anwenden des Skripts von -e
;
-l
: Entfernen Sie nachfolgende Zeilenumbrüche aus jeder Eingabezeile und fügen Sie jedem print
Anruf eine neue Zeile hinzu .
-a
: awk-mode, teile jede Eingabezeile in das Array auf @F
;
-F
: das Feldtrennzeichen für -a
.
Ein wichtiger Unterschied awk
besteht darin, dass perl
der -a
Switch Dateien in ein Array aufteilt. In Perl beginnen Arrays bei 0, nicht bei 1. Dies bedeutet, dass das 2. Feld tatsächlich ist $F[1]
und nicht $F[2]
. In Anbetracht dessen sind die perl
Äquivalente der oben genannten:
Drucken Sie Zeilen, deren 3. Feld ist foo
.
perl -ane 'print if $F[2] eq "foo"' file
Ändern des Trennzeichens in :
perl -F":" -ane 'print if $F[2] eq "foo"' file
Im Gegensatz zu awk
, perl
kann keine reguläre Ausdrücke als Feldtrennzeichen verwenden. Sie müssen ein bestimmtes Zeichen oder eine bestimmte Zeichenfolge sein.
Wie kann ich nur Zeilen drucken, deren 3. Feld nicht ist foo
?
perl -ane 'print unless $F[2] eq "foo"' file
Wie kann ich nur Zeilen drucken, deren 3. Feld übereinstimmt foo
?
perl -ane 'print if $F[2]=~/foo/' file
Wie kann ich nur Zeilen drucken, deren 3. Feld nicht übereinstimmt foo
?
perl -lane 'print unless $F[2]=~/foo/' file
Wie kann ich das 3. Feld ändern foo
?
Dieser ist in Perl etwas umständlicher. Der übliche Ansatz besteht darin, den Wert im @F
Array zu ändern und dann das Array zu drucken. Mit einfachen, durch Leerzeichen getrennten Dateien ist dies einfach:
perl -lane '$F[2]="foo"; print "@F"' file
Mit einem anderen Trennzeichen müssen Sie join
das Array. Andernfalls wird es durch Leerzeichen getrennt gedruckt:
perl -F: -lane '$F[2]="foo"; print join ":",@F' file
2. Verwenden Sie reguläre Ausdrücke
Die Idee hier ist, einen regulären Ausdruck (kurz "Regex") zu verwenden, der die Position der Zielzeichenfolge in der Zeile definiert. Zum Beispiel :
können wir in einer Datei, deren Felder durch getrennt sind, das 2. Feld finden, indem wir alles bis zum 1. :
(dem 1. Feld) abgleichen und dann nach dem zweiten suchen:
^[^:]*:[^:]*:
Dieser reguläre Ausdruck bedeutet:
^
: der Anfang der Zeile;
[^]
: eine negierte Zeichenklasse. [^:]
bedeutet "alles andere als :
";
*
: 0 oder mehr des vorherigen Musters;
:
: ein wörtliches :
;
Zusammengenommen bedeutet dies, dass das erste [^:]*
das erste Feld und das zweite das zweite Feld ist. Dies ist natürlich nicht sehr praktisch, wenn Sie nach dem 14. Feld suchen, aber es kann für einfachere Dinge nützlich sein. Wie implementieren wir dies, um unsere Daten zu manipulieren? Es gibt verschiedene Tools, die dies tun können. in diesen Beispielen werde ich verwenden , sed
aber Sie tun können , sehr ähnliche Dinge mit awk
, perl
oder python
.
Wie kann ich nur Zeilen drucken, deren 2. Feld ist foo
?
sed -n '/^[^:]*:foo:/p' file
Das -n
unterdrückt die normale Ausgabe und /regex/p
bedeutet "alle Zeilen drucken, mit denen der reguläre Ausdruck übereinstimmt".
Wie kann ich nur Zeilen drucken, deren 2. Feld nicht ist foo
?
sed '/^[^:]*:foo:/d' file
Die logische Umkehrung des Obigen. Hier /regex/d
bedeutet das "alle Zeilen löschen, mit denen der reguläre Ausdruck übereinstimmt".
Wie kann ich nur Zeilen drucken, deren 2. Feld übereinstimmt foo
?
sed -n '/^[^:]*:[^:]*foo/p' file
Wie kann ich nur Zeilen drucken, deren 2. Feld nicht übereinstimmt foo
?
sed '/^[^:]*:[^:]*foo/d' file
Wie kann ich das 2. Feld in ändern foo
?
sed 's/\([^:]*:\)[^:]*/\1foo/' file
Oder, da die sed
Substitution ein Auftreten von Mustern durch ihre Wiederholung mit einem einfachen numerischen Flag direkt ansprechen kann:
sed 's/[^:]*/foo/2' file