Quero classificar um arquivo delimitado por tabulações por um campo específico, preservando o cabeçalho. Estou usando awk
conforme descrito aquiordenar e uniq no awk, mas não consigo descobrir a quem dizer sort
que 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 sort
que 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 sort
dentro 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/ \047
para 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