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.