Wie drucke ich die dritte bis letzte Spalte?


121

Ich versuche, die ersten beiden Spalten (von denen ich nicht interessiert bin) aus einer DbgView-Protokolldatei zu entfernen. Ich kann anscheinend kein Beispiel finden, das ab Spalte 3 bis zum Ende der Zeile gedruckt wird. Beachten Sie, dass jede Zeile eine variable Anzahl von Spalten hat.


Antworten:


109

... oder eine einfachere Lösung: cut -f 3- INPUTFILE Fügen Sie einfach das richtige Trennzeichen (-d) hinzu und Sie haben den gleichen Effekt.


9
Beachten Sie, dass dies nur funktioniert, wenn das Trennzeichen zwischen allen Spalten genau gleich ist. Beispielsweise können Sie das Ausschneiden nicht mit einem Trennzeichen wie \ d + verwenden. (Das weiß ich.)
Zach Wily

72
Wenn die Frage den Titel awk trägt, ist es unangemessen, eine andere Antwort als awk zu akzeptieren. Was ist, wenn Leute es für awk-Skripte brauchen? Diese Antwort hätte nur ein Kommentar sein sollen.
Syaz

24
@SyaZ: Normalerweise würde ich zustimmen, aber angesichts der Menge an "unentgeltlichen Awk" auf diesem Board dachte ich, dass es notwendig ist, einen alternativen Weg zu zeigen, um die Aufgabe zu erledigen. Wären Sie nicht dankbar, wenn Ihnen jemand einen einfacheren und schnelleren Weg zeigen würde, um dieselbe Aufgabe zu erledigen? Vielleicht ist das Poster der Meinung, dass awk der einzige Weg ist, dies zu tun, da die Anzahl der Antworten auf andere Fragen nicht falsch, aber auf jeden Fall verbesserungsfähig ist?
Marcin

12
Dafür ist der Kommentar da. Akzeptieren Sie die beste Antwort und geben Sie bessere Vorschläge für Kommentare. Wenn Leute anfangen, Antworten zu veröffentlichen, die Fragen nicht genau beantworten, wird es bei der Suche (in meinem Fall) ärgerlich.
Syaz

12
Nicht nur das Trennzeichen muss zwischen allen Spalten gleich sein, sondern es muss genau ein Trennzeichen zwischen den Spalten vorhanden sein. Wenn Sie also mit Programmen arbeiten, deren Ausgabe an Trennzeichen ausgerichtet ist, ist es besser, awk zu verwenden.
Sknaumov

110
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' ist kompakter. :)
user172818

1
Danke, lh3. Ich habe gerade für das Gawk-Handbuch kopiert und eingefügt. :)
Jonathan Feinberg

22
Dies schlägt bei mehreren Zeilen fehl. Jede Spalte wird beim Drucken mit print
meso_2600

12
Um das Problem der geteilten Ausgabe zu beheben , schlage ich folgende Lösung vor: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfdruckt das Zeilenumbruchzeichen nicht, während print ""Zeilenumbruch hinzugefügt wird, nachdem die anderen Felder gedruckt wurden)
lauhub

1
Oder : echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', was gibt : 3 4 5 6 7 8 9 10.
X-Yuri

106

23
Ich bin etwas spät
dran

Das Drucken eines internen Bereichs ist ebenfalls möglich: `` `# von $ 3 (enthalten) bis $ 6 (ausgeschlossen); Echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, index ($ 0, $ 3), length ($ 0) -index ($ 0, $ 6) -1)}'; # gibt 3,4,5```
splaisan

34

Die Antwort von Jonathan Feinberg druckt jedes Feld in einer separaten Zeile. Sie können printfden Datensatz für die Ausgabe in derselben Zeile neu erstellen, aber Sie können die Felder auch einfach einen Sprung nach links verschieben.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Beachten Sie, dass dies nur für Gnu awk funktioniert. Eine Dekrementierung NFist von POSIX nicht zulässig.
kvantour

1
@kvantour: Es funktioniert in gawk, mawk, MacOS awk (nawk?). POSIX scheint zu schweigen, ob NFes dekrementiert werden kann.
Bis auf weiteres angehalten.

Es ist eine dieser lustigen dunklen Ecken von awk .
kvantour

19
awk '{$1=$2=$3=""}1' file

NB: Diese Methode hinterlässt "Leerzeichen" in 1,2,3-Feldern, ist jedoch kein Problem, wenn Sie nur die Ausgabe betrachten möchten.


Verfolgen Sie diesen Befehl mit `| sed s / ^ \ * // | Spalte -t`, um führende Leerzeichen zu entfernen und die verbleibenden Spalten auszurichten
MSpreij

Was bedeutet das letzte 1? Mit welchem ​​Schlüsselwort soll ich suchen awk?
Itachi


1
@ Nathan Sie lösen dieses Problem als{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

Wenn Sie die Spalten nach dem 3. beispielsweise in derselben Zeile drucken möchten, können Sie Folgendes verwenden:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Beispielsweise:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Es wird gedruckt:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Wie wir sehen können, wird die Gehaltsabrechnung auch bei Leerzeichen in der richtigen Zeile angezeigt.


Schnell und schlank. Danke;)
9nz9

Dies ist ausgezeichnet, außer ich habe ein Problem damit, dass $ NF ausgeschlossen wird. Wenn ich die Bedingung (<= NF) setze, erhalte ich das letzte Feld, aber das erste Zeichen des ersten Feldes wird abgeschnitten. Verstehe ich etwas in Bezug auf Funktionalität falsch?
Ken Ingram

Mein Problem scheint zu sein, dass ^ M am Ende der letzten Spalte hängen bleibt. Ich sehe nicht, wie ich es entfernen soll.
Ken Ingram

8

Was ist mit der folgenden Zeile:

awk '{$ 1 = $ 2 = $ 3 = ""; Druckdatei

Basierend auf dem Vorschlag von @ ghostdog74. Meins sollte sich besser verhalten, wenn Sie Linien filtern, dh:

awk '/ ^ exim4-config / {$ 1 = ""; Druckdatei

Kurz und einfach. Könnte auch sed 's/\s\+//g'am Ende des Befehls Pipe & Add hinzufügen , um führende Leerzeichen zu
kürzen

8
awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Dies zerhackt, was vor dem angegebenen Feld nr., N steht, und druckt den gesamten Rest der Zeile, einschließlich Feld nr.N, und behält den ursprünglichen Abstand bei (es wird nicht neu formatiert). Es spielt keine Rolle, ob die Zeichenfolge des Feldes auch an einer anderen Stelle in der Zeile angezeigt wird, was das Problem mit Daisaas Antwort ist.

Definieren Sie eine Funktion:

fromField () { 
awk -v m="\x0a" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

Und benutze es so:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

Die Ausgabe behält alles bei, einschließlich nachfolgender Leerzeichen

Funktioniert gut für Dateien, in denen '/ n' das Datensatztrennzeichen ist, sodass Sie das Zeichen für neue Zeilen nicht in den Zeilen haben. Wenn Sie es mit anderen Datensatztrennzeichen verwenden möchten, verwenden Sie:

awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

beispielsweise. Funktioniert gut mit fast allen Dateien, solange sie kein hexadezimales Zeichen nr verwenden. 1 innerhalb der Zeilen.


4

Der folgende Befehl awk druckt die letzten N Felder jeder Zeile und am Ende der Zeile ein neues Zeilenzeichen:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Nachfolgend finden Sie ein Beispiel, das den Inhalt des Verzeichnisses / usr / bin auflistet, die letzten 3 Zeilen enthält und dann die letzten 4 Spalten jeder Zeile mit awk druckt:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

Zuerst finden Sie die Position des Anfangs der dritten Spalte. Mit substr drucken Sie die gesamte Zeile ($ 0) beginnend an der Position (in diesem Fall a) bis zum Ende der Zeile.


3

Nun, Sie können den gleichen Effekt leicht mit einem regulären Ausdruck erzielen. Angenommen, das Trennzeichen ist ein Leerzeichen, würde es so aussehen:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
Ich würde Regex vermeiden. Es ist wahrscheinlich langsamer und einfacher, versehentlich etwas durcheinander zu bringen.
Cascabel

1
Es verkürzt es so: awk '{ sub(/([^ ]+ +){2}/, ""); print }'Das Muster wird zweimal entfernt.
Erik


2

Perl-Lösung:

perl -lane 'splice @F,0,2; print join " ",@F' file

Diese Befehlszeilenoptionen werden verwendet:

  • -n Schleife um jede Zeile der Eingabedatei, drucke nicht automatisch jede Zeile

  • -l Entfernt Zeilenumbrüche vor der Verarbeitung und fügt sie anschließend wieder hinzu

  • -aAutosplit-Modus - Teilen Sie die Eingabezeilen in das @ F-Array. Standardmäßig wird auf Leerzeichen aufgeteilt

  • -e Führen Sie den Perl-Code aus

splice @F,0,2 Entfernt sauber die Spalten 0 und 1 aus dem @ F-Array

join " ",@F Verbindet die Elemente des @ F-Arrays mit einem Leerzeichen zwischen den einzelnen Elementen

Wenn Ihre Eingabedatei durch Kommas und nicht durch Leerzeichen getrennt ist, verwenden Sie -F, -lane


Python-Lösung:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

Ein bisschen spät hier, aber keines der oben genannten schien zu funktionieren. Versuchen Sie dies, indem Sie mit printf Leerzeichen dazwischen einfügen. Ich habe mich entschieden, am Ende keine Newline zu haben.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

Druckt Datensätze vom 4. bis zum letzten Feld in derselben Reihenfolge wie in der Originaldatei


Entschuldigung, das war keine ganz richtige Antwort. es ist zu spezifisch, aber ich weiß nicht, wie ich es löschen soll
Massimo


0

Wenn es nur darum geht, die ersten beiden Felder zu ignorieren, und wenn Sie beim Maskieren dieser Felder kein Leerzeichen möchten (wie dies bei einigen der obigen Antworten der Fall ist):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

Die ersten beiden Spalten werden gelöscht und sedführende Leerzeichen entfernt.


-2

In AWK werden Spalten als Felder bezeichnet, daher ist NF der Schlüssel

alle Zeilen:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

Nur erste Reihe:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
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.