
Estou tentando classificar alguns dados usando sort
. Percebi que estava classificando por dígito em vez de número, então adicionei o -n
sinalizador. Aparentemente, ele classifica apenas numericamente o primeiro campo. Dividir por campo é um problema, pois as linhas têm números variados de campos (e, francamente, não consigo entender seu comportamento). Aqui estão alguns dados de amostra próximos o suficiente com os quais eu estava brincando:
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" | sort -n
Input Want Expect? sort -n -n -k1,1 -k2,2 -k3,3 -k4,4…
b b 1 8 2 a 1 23 44 a 1 b a 1
23 44 8 15 a 7 23 9 a 7 b a 10
b 3 23 9 b a 1 8 15 b 1 b a 2
a 7 23 44 b a 2 8 2 b 10 b b 1
b b 2 a 1 b a 10 a 1 b 2 b b 10
a 1 a 7 b b 1 a 7 b 3 b b 2
b a 10 b 1 b b 2 b 1 b a 1 a 1
b b 10 b 2 b b 10 b 10 b a 10 b 1
b 1 b 3 b 1 b 2 b a 2 b 2
b a 1 b 10 b 2 b 3 b b 1 b 3
8 2 b a 1 b 3 b a 1 b b 10 a 7
b 10 b a 2 b 10 b a 10 b b 2 b 10
8 15 b a 10 8 2 b a 2 8 15 8 2
b a 2 b b 1 8 15 b b 1 8 2 8 15
23 9 b b 2 23 9 b b 10 23 44 23 9
b 2 b b 10 23 44 b b 2 23 9 23 44
Idealmente, eu gostaria de fazê-lo funcionar naquela mesma máquina, que possui GNU coreutils sort 5.93. Eu gostaria de lidar com isso com ferramentas Unix simples; Não quero apenas entregar o problema ao perl, etc. Espero um equivalente ao [imaginário]sort --numeric-sort --all-fields --actually-work
Responder1
Acho que seu problema é que você não entende o sort
que está fazendo. A classificação básica é baseada em valores de caracteres ASCII, onde os números estão antes das letras maiúsculas e antes das minúsculas: '1' == 49, 'A' == 65, 'a' = 97. Isso explica a sort
coluna, onde números como '23 'é classificado antes de '8', que é antes de 'b b': o valor ASCII para '2' é 50, o valor ASCII para '8' é 56 e para 'b' é 98.
Ao classificar numericamente ( sort -n
), as entradas não numéricas são classificadas pelo método regular, mas interpretadas como zero quando comparadas a números, como 23 ou 8; mas como o valor é tratado como um número, não como um valor de caractere, '8' vem antes de '23'. Portanto, as entradas alfabéticas serão classificadas antes das entradas numéricas.
Sua melhor aposta é normalizar os dados para que cada coluna tenha o mesmo tipo de valor: todos os números ou todos alfanuméricos, e classificar adequadamente.
Na última coluna (classificação por campo), ele classificará primeiro as entradas com mais campos, pois você está especificando explicitamente 4 (ou mais) campos. Então (1,2,3) seria antes de (1,2). Sem a -k
opção, sort leva em consideração a linha como um todo.
Você pode ler mais informações sobre oinformações coreutils classificarpágina.
Responder2
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" \
| sed -r 's/[a-z]/9999&/g' | sort -n -k1 -k2 -k3 | sed 's/9999//g'
18 2
18 15
23 9
23 44
a 1
b 1
b 2
b 3
a 7
b 10
b a 1
b b 1
b a 2
b b 2
b a 10
b b 10
É isso que você quer? Classificar numericamente, se for numérico, e números antes de outros caracteres?
Eu prefixo cada String com um número alto, para colocar as Strings por último, classificando, e removo os números altos (9999) no final.
Responder3
Com o benefício proporcionado por alguns anos de desenvolvimento, sort -V
produz sort 8.26
apenas o resultado desejado:
$ echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n8 2\nb 10\n8 15\nb a 2\n23 9\nb 2" \
| sort -V
8 2
8 15
23 9
23 44
a 1
a 7
b 1
b 2
b 3
b 10
b a 1
b a 2
b a 10
b b 1
b b 2
b b 10