Classifique dentro do awk com tab como separador de campo

Classifique dentro do awk com tab como separador de campo

Quero classificar um arquivo delimitado por tabulações por um campo específico, preservando o cabeçalho. Estou usando awkconforme descrito aquiordenar e uniq no awk, mas não consigo descobrir a quem dizer sortque o separador de campos é uma guia.

Dados do brinquedo:

$ 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

Quando tento informar explicitamente sortque o separador de campos é uma guia, recebo este erro, que acredito estar relacionado a problemas de cotação:

$ 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

Como especifico o separador de colunas sortdentro do `awk? Obrigado

A interface web do SE está fazendo um trabalho melhor de realce de sintaxe do que o Notepad++; aqui estão algumas coisas que tentei:

$ 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

Responder1

escolheu uma destas opções:

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

\011é o código Octeto ASCII paraAbacaractere/ \047para aspas simples '

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 }'

e muitos mais …; lerProblemas de cotação do Shell no awk; Veja tambémSequências de escape no awk

Responder2

Esta pode não ser uma maneira adequada, mas é simples e não há necessidade de brincar com o caractere de tabulação ...: D

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

Responder3

FWIW, aqui está como eu resolveria seu problema real de classificar os dados, mas preservando o cabeçalho no topo:

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

O procedimento acima funciona acrescentando 0 ou 1 aos dados de entrada (0 para a primeira linha, 1 para todas as outras linhas) para que você possa classificar primeiro esse indicador e depois sua chave real de seu interesse e, em seguida, apenas remover o campo adicionado novamente .

Aqui está funcionando em etapas:

$ 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

informação relacionada