Durch Komma getrennte Druckspalte über die Awk-Befehlszeile


77

Ich habe hier ein Problem. Ich muss eine Spalte in einer Textdatei mit awk drucken. Die Spalten werden jedoch überhaupt nicht durch Leerzeichen getrennt, sondern nur durch ein einziges Komma. Sieht ungefähr so ​​aus:

column1,column2,column3,column4,column5,column6

Wie würde ich die dritte Spalte mit awk ausdrucken?


1
Warum möchten Sie verwenden awk? IMHO ist dies ein sehr einfaches Problem. Haben Sie einen Versuch, es zu lösen?
TrueY

Antworten:


121

Versuchen:

awk -F',' '{print $3}' myfile.txt

Hier in -F sagst du zu awk, dass "," als Feldtrennzeichen verwendet wird.


Ich habe viele Seiten durchgesehen und viel mehr Ergebnisse erzielt, und dies war bei weitem das Beste :) Danke
AJC

40

Wenn Sie nur das dritte Feld jeder Zeile drucken müssen, wobei jedes Feld durch ein Komma getrennt ist, können Sie cut verwenden:

cut -d, -f3 file
  • -d, Setzt das Trennzeichen auf ein Komma
  • -f3 Gibt an, dass nur das dritte Feld gedruckt werden soll

1
Dies ist die beste Antwort auf diese Frage. awkkommt sehr praktisch, wenn ich sagen möchte, ich möchte [col1]:[col5]mit verschiedenen
Dels

26

Versuche dies awk

awk -F, '{$0=$3}1' file
column3
  • , Felder teilen durch ,
  • $0=$3 Setzen Sie die Zeile auf Nur Feld 3
  • 1Alles ausdrucken. ( hier erklärt )

Dies könnte auch verwendet werden:

awk -F, '{print $3}' file

4
Dies ist nicht nur kürzer, sondern auch für jemanden, der mit awk nicht vertraut ist, viel schwieriger zu verstehen. Es lohnt sich, eine Erklärung hinzuzufügen, um diese Antwort nützlicher zu machen.
Tom Fenech

1
+1. Ein bisschen kryptisch, funktioniert aber wie ein Schaffhausen.
TrueY

1
@ TomFenech: Ich denke, es cut -d, -f3 fileist so kryptisch wie dieses, wenn jemand nicht vertraut ist cut. ;)
TrueY

3
@TrueY gewährt, obwohl ein Unterschied darin besteht, dass cut --helpalles erklärt wird, was Sie wissen müssen, während awk --helpdies nicht der Fall ist . Vielleicht hätte ich mich entscheiden sollen cut --delimiter=, --fields=3 file, obwohl ich meine Zweifel habe, dass die längeren Schalter tragbar sind :)
Tom Fenech

2

Eine einfache, obwohl -lose Lösung in ::

while IFS=, read -r a a a b; do echo "$a"; done <inputfile

Es funktioniert dann schneller für kleine Dateien (<100 Zeilen) da es weniger Ressourcen verbraucht (vermeidet das Aufrufen der teuren forkundexecve Systemaufrufe).

EDIT von Ed Morton (Entschuldigung für die Antwort, ich weiß nicht, ob es einen besseren Weg gibt, dies zu beheben):

Um den Mythos auszuräumen, dass die Shell für kleine Dateien schneller als awk ausgeführt wird:

$ wc -l file
99 file

$ time while IFS=, read -r a a a b; do echo "$a"; done <file >/dev/null

real    0m0.016s
user    0m0.000s
sys     0m0.015s

$ time awk -F, '{print $3}' file >/dev/null

real    0m0.016s
user    0m0.000s
sys     0m0.015s

Ich gehe davon aus, dass das Shell-Skript in einem Bruchteil eines Augenblicks schneller ausgeführt wird als das awk-Skript, wenn Sie eine WIRKLICH kleinste Datei erhalten. Aber wen interessiert das?

Und wenn Sie nicht glauben, dass es schwieriger ist, robuste Shell-Skripte als awk-Skripte zu schreiben, sehen Sie sich diesen Fehler in dem von Ihnen veröffentlichten Shell-Skript an:

$ cat file
a,b,-e,d
$ cut -d, -f3 file
-e
$ awk -F, '{print $3}' file
-e
$ while IFS=, read -r a a a b; do echo "$a"; done <file

$

1
While readSchleifen sind deutlich langsamer als awk, selbst wenn sie mit winzigen Dateien schneller wären, wäre der Geschwindigkeitsunterschied vernachlässigbar.

@ Jidder: Du hast recht! IMHO deshalb ist es sinnlos, awk für kleine Dateien zu verwenden.
TrueY

1
@ EdMorton: Du hast recht. Für größere und komplexere Probleme verwende ich definitiv awk (häufiger von einem Bash- Skript aufgerufen ), aber für kleine Dateien und einfache Aufgaben verwende ich Pure Bash . Andererseits bevorzuge ich für noch komplexere Jobs Perl für die Skripterstellung.
TrueY

1
@ EdMorton: Du hast wieder recht und es scheint, dass mit echo damit nicht einfach gelöst werden kann. In diesem Fall kann man das verwenden printf "%s\n" "$a", um das loszuwerden. Dies ist auch ein Bash - Einbau .
TrueY

1
@ EdMorton: Du hast recht! Wenn jemand ein Werkzeug verwendet, muss er die möglichen Probleme kennen. Daher empfehle ich jedem, ein geeignetes Werkzeug zu verwenden. Wenn ich ein Kernelmodul schreibe, verwende ich definitiv kein Bash . ;) Aber für solch eine kleine Aufgabe kann es genug sein.
Richtig
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.