Sortieren innerhalb von awk mit Tab als Feldtrennzeichen

Sortieren innerhalb von awk mit Tab als Feldtrennzeichen

Ich möchte eine tabulatorgetrennte Datei nach einem bestimmten Feld sortieren und dabei den Header beibehalten. Ich verwende awkwie hier beschriebensortieren und eindeutig in awk, aber ich kann nicht herausfinden, wem ich sagen kann, sortdass der Feldtrenner ein Tabulator ist.

Spielzeugdaten:

$ echo -e "head_1\thead_2\thead_3" > file.tsv
$ echo -e "aaa zzz\tc\t300" >> file.tsv
$ echo -e "bbb yyy ooo\ta\t100" >> file.tsv
$ echo -e "ccc xxx nnn\tb\t200" >> file.tsv
$ column -ts $'\t' file.tsv
head_1       head_2  head_3
aaa zzz      c       300
bbb yyy ooo  a       100
ccc xxx nnn  b       200

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2" }' file.tsv | column -ts $'\t' 
head_1       head_2  head_3
ccc xxx nnn  b       200           ## note these data are sorted 
bbb yyy ooo  a       100           ## based on the xxx/yyy/zzz 
aaa zzz      c       300           ## not the a/b/c

Wenn ich versuche, explizit anzugeben, sortdass der Feldtrenner ein Tabulator ist, erhalte ich diese Fehlermeldung, die meiner Meinung nach mit Anführungszeichenproblemen zusammenhängt:

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'\t'" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

Wie lege ich den Spaltentrenner für sortinnerhalb von `awk fest? Danke

Die Syntaxhervorhebung der Weboberfläche von SE ist besser als die von Notepad++. Hier sind ein paar Dinge, die ich ausprobiert habe:

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'$'\t''" }' file.tsv | column -ts $'\t'
head_1       head_2  head_3
aaa zzz      c       300
bbb yyy ooo  a       100
ccc xxx nnn  b       200


$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'\t'" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t "'$'\t''"" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t "'$'\t'' }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

Antwort1

Wählen Sie eine dieser Optionen:

... | "sort -k2 -t \\\t "
... | "sort -k2 -t \"\t\" "
... | "sort -k2 -t'\''\t'\'' "
... | "sort -k2 -t \047\011\047" ## preferred 

\011ist der Octet ASCII-Code fürTabZeichen/ \047für einfaches Anführungszeichen '

awk -v q="'" ... { print | "sort -k2 -t " q "\t" q }'
awk -v tb="'\t'" ... { print | "sort -k2 -t " tb }'
awk -v tb=$'\t' ... { print | "sort -k2 -t \"" tb "\"" }'
awk -v tb=$'\t' -v q="'" ... { print | "sort -k2 -t " q tb q }'

und viele mehr …; lesenShell-Zitatprobleme in awk; siehe auchEscape-Sequenzen in awk

Antwort2

Dies ist vielleicht keine richtige Einzeiler-Methode, aber es ist einfach und man muss nicht mit der Tabulatortaste herumspielen … :D

var=$(head -1 file.tsv);perl -ne '{ print $_ if $. > 1; }'  file.csv| sort -k2 | sed "1 i $var" | column -ts "\t"

Antwort3

So würde ich Ihr eigentliches Problem, die Daten zu sortieren und dabei die Kopfzeile oben beizubehalten, lösen:

awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3 | cut -f2-

Das Obige funktioniert, indem den Eingabedaten eine 0 oder 1 vorangestellt wird (0 für die erste Zeile, 1 für alle anderen Zeilen), sodass Sie zuerst nach diesem Indikator und dann nach dem für Sie wichtigen Schlüssel sortieren und das hinzugefügte Feld anschließend einfach wieder entfernen können.

So funktioniert es schrittweise:

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv
0   head_1  head_2  head_3
1   aaa zzz c   300
1   bbb yyy ooo a   100
1   ccc xxx nnn b   200

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3
0   head_1  head_2  head_3
1   bbb yyy ooo a   100
1   ccc xxx nnn b   200
1   aaa zzz c   300

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3 | cut -f2-
head_1  head_2  head_3
bbb yyy ooo a   100
ccc xxx nnn b   200
aaa zzz c   300

verwandte Informationen