Classificando várias chaves com a classificação Unix


137

Eu tenho arquivos potencialmente grandes que precisam ser classificados por chaves 1-n. Algumas dessas teclas podem ser numéricas e outras não. Este é um arquivo colunar de largura fixa, portanto não há delimitadores.

Existe uma boa maneira de fazer isso com a classificação Unix? Com uma tecla, é tão simples quanto usar '-n'. Eu li a página de manual e procurei no Google brevemente, mas não encontrei um bom exemplo. Como eu realizaria isso?

Nota: Excluí o Perl por causa do potencial de tamanho do arquivo. Seria o último recurso.


Uma ou duas linhas de dados de exemplo seriam realmente úteis para criar uma linha de comando de exemplo. Além disso, as chaves "1-n" significam que você precisa classificar por um número variável de chaves? Fazer isso sem scripting vai ser divertido ...
— Ken Gentil

Eu tenho um wrapper PHP em torno do comando de classificação para ativar o recurso 1-n.
— Chris Kloberdanz

Respostas:


69

Use a -kopção (ou --key=POS1[,POS2]). Pode aparecer várias vezes e cada tecla pode ter opções globais (como npara classificação numérica)


7
Na página do manual de classificação: "POS é F [.C] [OPTS], onde F é o número do campo e C a posição do caractere no campo; ambos são a origem 1." Consulte a página do manual para obter a documentação completa.
— Adam Rosenfield

49
Veja também a resposta de andras, se você não quiser ficar louco.
— ron

1
Ambos os comentários acima são precisos e aditivos. Obrigado, senhores.
— Ken Gentil

314

Tome cuidado, porém:

Se você deseja classificar o arquivo principalmente pelo campo 3 e, secundariamente, pelo campo 2, deseja o seguinte:

sort -k 3,3 -k 2,2 < inputfile

Não é isso: sort -k 3 -k 2 < inputfile que classifica o arquivo pela cadeia de caracteres desde o início do campo 3 até o final da linha (que é potencialmente exclusivo).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)

8
Mudança de vida. Obrigado.
— Davidtbernal

2
Ops! Agora eu tenho que corrigir um script porque antes eu só vi a primeira resposta acima ... coisa boa que eu não dependia da saída do script ainda ....
— Wildcard

Agradável! Agora, e se eu quiser que o campo 3 seja numericamente e classificado inversamente, enquanto o campo 2 seja não numericamente e normal (crescente) classificado? :)
— Arun

2
O @Arun POS é explicado no final da página de manual. Você acabou de anexar as opções de pedidos ao número do campo assim:sort -k 3,3nr -k 2,2
— andras

1
Aargh. Que interface contra-intuitiva: -k2deve ser -k2,2e uma vírgula à direita -k2,deve ser 'fim de linha mágico padrão ou o que for'.
— android.weasel

94

A opção -k é o que você deseja.

-k 1.4,1.5n -k 1.14,1.15n

Usaria as posições de caracteres 4-5 no primeiro campo (é um campo para largura fixa) e classificaria numericamente como a primeira tecla.

A segunda chave seria os caracteres 14-15 no primeiro campo também.

(editar)

Exemplo (tudo o que tenho é DOS / cygwin à mão):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

para os dados:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Classifica a listagem do diretório pelo número do mês (pos 4-5) numericamente e depois pelo nome do arquivo (pos 40-60) ao contrário. Como não há guias, é todo o campo 1 para classificar.


É apenas um campo se não houver espaços em branco nos dados de entrada. No entanto, seu exemplo é útil.
— 11138 Jonathan Leffler

Correção: se não houver / tabs / nos dados de entrada. Na saída do comando 'dir' do DOS, não há guias.
— Clinton Pierce

Os exemplos de como usar as opções (numérico, reverso) são extremamente úteis, pois é quase impossível descobrir como usar apenas na página de manual e as outras respostas não mencionaram isso. Eu gostaria de poder +2 por isso. ;)
— msb 21/10

22

Aqui está um para classificar várias colunas em um arquivo csv por ordem numérica e de dicionário, colunas 5 e depois como ordem de dicionário

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Observe que -k1,1n significa numérico, começando na coluna 1 e terminando na coluna 1. Se eu tivesse feito abaixo, teria concatenado as colunas 1 e 2, tornando 1,10 classificado como 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga

1
Esta é a melhor resposta, porque mostra como usar opções diferentes para diferentes colunas
— xaxa

12

Eu acredito no seu caso, algo como

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

vai funcionar melhor. @ é o separador de campos, verifique se é um caractere que não aparece em lugar nenhum. sua entrada é considerada como consistindo em uma coluna.

Edit: aparentemente Clintp já deu uma resposta semelhante, desculpe. Como ele aponta, as bandeiras 'n' e 'r' podem ser adicionadas a todas as opções -k ....


Embora o separador padrão de acordo com docs gnu.org/software/coreutils/manual/html_node/… seja espaço, às vezes a contagem de campos não é o que você esperaria. Talvez, como outros já disseram aqui, devido à configuração da localidade LC_CTYPE. Em caso de dúvida, conte desde o início da linha!
— Brad Dre

5

Observe que também pode ser desejado estabilizar a classificação com o -scomutador, para que as linhas igualmente classificadas também mantenham sua ordem relativa original na saída.


2

Eu só quero adicionar algumas dicas, ao usar a classificação, tenha cuidado com o local que afeta a ordem da comparação de chaves. Eu normalmente uso explicitamente LC_ALL = C para tornar o local o que eu quero.


LC_ALL = C também pode resultar em uma aceleração bastante!
— mat Kelcey
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.