Der Befehl „Ausschneiden“ extrahiert Felder in ausgerichteten Spalten nicht richtig

Der Befehl „Ausschneiden“ extrahiert Felder in ausgerichteten Spalten nicht richtig

Ich habe eine Textdatei in der ich die Felder 3,4,5 und 8 ausschneiden muss:

219 432 4567 Harrison     Joel     M 4540 Accountant      09-12-1985
219 433 4587 Mitchell     Barbara  C 4541 Admin Asst      12-14-1995
219 433 3589 Olson        Timothy  H 4544 Supervisor      06-30-1983
219 433 4591 Moore        Sarah    H 4500 Dept Manager    08-01-1978
219 431 4527 Polk         John     S 4520 Accountant      09-22-1998
219 432 4567 Harrison     Joel     M 4540 Accountant      09-12-1985
219 432 1557 Harrison     James    M 4544 Supervisor      01-07-2000

Da das Trennzeichen standardmäßig ein Tabulator ist, lautet der Befehl zum Extrahieren der Felder:

cut -f 3,4,5,8 filename

Die Sache ist, dass die Ausgabe mit dem ursprünglichen Dateiinhalt identisch ist. Was passiert hier? Warum funktioniert das nicht?

Antwort1

Nicht alle Leerzeichen zwischen den Spalten scheinen Tabulatoren zu sein, daher cutkönnen Sie nicht das erreichen, was Sie möchten. Ich würde awkstattdessen vorschlagen, zu verwenden. Es ist flexibler als cutbeim Parsen von Datenspalten, wie Sie es erreichen möchten:

$ awk '{print $3,$4,$5,$8}' data.txt

Beispiel

$ awk '{print $3,$4,$5,$8}' data.txt 
4567 Harrison Joel Accountant
4587 Mitchell Barbara Admin
3589 Olson Timothy Supervisor
4591 Moore Sarah Dept
4527 Polk John Accountant
4567 Harrison Joel Accountant
1557 Harrison James Supervisor

Sie können die Ausgabe auch mit dem columnfolgenden Befehl strukturieren:

$ awk '{print $3,$4,$5,$8}' data.txt |column -t
4567  Harrison  Joel     Accountant
4587  Mitchell  Barbara  Admin
3589  Olson     Timothy  Supervisor
4591  Moore     Sarah    Dept
4527  Polk      John     Accountant
4567  Harrison  Joel     Accountant
1557  Harrison  James    Supervisor

Sie können alles auch einfach mit awkund erledigen printf:

$ awk '{printf "%s\t%-20s\t%s\n",$3,$4" "$5,$8}' data.txt 
4567    Harrison Joel           Accountant
4587    Mitchell Barbara        Admin
3589    Olson Timothy           Supervisor
4591    Moore Sarah             Dept
4527    Polk John               Accountant
4567    Harrison Joel           Accountant
1557    Harrison James          Supervisor

Schnitt überarbeitet

Die oben genannten Methoden funktionieren ganz gut, aber sie verarbeiten keine Zeilen, in denen der Wert für eine bestimmte Spalte Leerzeichen enthält. Beispielsweise wird die Zeile mit „Dept Manager“ auf „Dept“ gekürzt.

Wenn garantiert werden kann, dass die Daten die gezeigten Strukturen aufweisen, können wir sie verwenden, cutaber statt sie anhand eines Trennzeichens aufzuteilen, können wir die Anzeige einfach anhand der tatsächlichen Positionen der Zeichen vornehmen.

Beispiel

Dadurch wird der Text aus der Datei ausgeschnitten data.txtund die Positionen 9 bis 13 und 14 bis 35 usw. gedruckt.

$ cut -c 9-13,14-35,43-58 data.txt 
4567 Harrison     Joel     Accountant      
4587 Mitchell     Barbara  Admin Asst      
3589 Olson        Timothy  Supervisor      
4591 Moore        Sarah    Dept Manager    
4527 Polk         John     Accountant      
4567 Harrison     Joel     Accountant      
1557 Harrison     James    Supervisor      

awk erneut besucht

Awk kann auch so eingestellt werden, dass Text basierend auf seiner Position und nicht anhand eines Trennzeichens herausgezogen wird. Dies ist allerdings ausführlicher, aber der Vollständigkeit halber wird hier beschrieben, wie es geht.

$ awk '{
    printf "%s\t%-20s\t%s\n",substr($0,9,5),substr($0,14,22),substr($0,43,16)
  }' data.txt
4567    Harrison     Joel       Accountant      
4587    Mitchell     Barbara    Admin Asst      
3589    Olson        Timothy    Supervisor      
4591    Moore        Sarah      Dept Manager    
4527    Polk         John       Accountant      
4567    Harrison     Joel       Accountant      
1557    Harrison     James      Supervisor      

awk FELDBREITEN

Wenn Sie eine Variante von GNU verwenden, awkkönnen Sie die Variable verwenden, FIELDWIDTHSum die statische Größe jedes Felds anzugeben. Dies ist viel sauberer als die substrMethode, wenn Sie darauf zugreifen können. Außerdem können Sie Felder effektiv zusammenfügen, die sonst als separate Felder analysiert würden.

$ awk 'BEGIN { FIELDWIDTHS="4 4 5 24 5 16 11" }{ print $3,$4,$5,$6 }' data.txt 
4567  Harrison     Joel     M  4540  Accountant      
4587  Mitchell     Barbara  C  4541  Admin Asst      
3589  Olson        Timothy  H  4544  Supervisor      
4591  Moore        Sarah    H  4500  Dept Manager    
4527  Polk         John     S  4520  Accountant      
4567  Harrison     Joel     M  4540  Accountant      
1557  Harrison     James    M  4544  Supervisor      

Antwort2

Ich vermute, dass es sich nicht um Tabulatoren handelt. Der Grund, warum ich nicht glaube, dass es sich um Tabulatoren handelt, ist, dass es anscheinend einwandfrei funktioniert, wenn ich die Datei kopiere und einfüge und die Felder manuell tabelliere . Wenn Sie die Felder und Werte nicht erneut tabellieren möchten , cut -f 3,4,5,8 filenameist dies möglicherweise besser für Sie.cat filename | awk '{print $3, $4, $5, $8}'

verwandte Informationen