classifica numericamente cada campo, variando as contagens de campo

7

Estou tentando classificar alguns dados usando sort . Percebi que estava classificando por dígito em vez de número, então adicionei o sinalizador -n . Então, aparentemente, só numericamente classifica no primeiro campo embora. Quebrar por campo é um problema, já que as linhas têm números variados de campos (e, francamente, não consigo entender seu comportamento). Veja alguns dados de amostra próximos o suficiente com os quais eu estava jogando:

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 trabalhar na mesma máquina, que tem GNU coreutils sort 5.93. Eu gostaria de lidar com isso com ferramentas simples de unix; Eu não quero apenas entregar o problema para perl, etc. Eu estou esperando por um equivalente do [imaginário] sort --numeric-sort --all-fields --actually-work

    
por Joel Reid 20.03.2012 / 20:25

3 respostas

7

Eu acho que o problema é que você não entende o que o sort está fazendo. A classificação básica é baseada em valores de caracteres ASCII, onde os números são antes de maiúsculas, que são antes de minúsculas: '1' == 49, 'A' == 65, 'a' = 97. Isso explica a coluna sort , em que 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 aos números, como 23 ou 8; mas como o valor é tratado como um número, não como um valor de caractere, '8' é anterior a '23'. Assim, 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 os alfanuméricos, e classifique apropriadamente.

Na última coluna (classificação por campo), ele classificará as entradas com mais campos primeiro, desde que você esteja explicitamente especificando 4 (ou mais) campos. Então (1,2,3) seria antes (1,2). Sem a opção -k , o sort considera a linha como um todo.

Você pode ler mais informações na página info coreutils sort .     

por 20.03.2012 / 20:55
3
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, o que você quer? Ordenar numericamente, se numérico e números antes de outros caracteres?

Prefixo cada String com um número alto, para colocar as Strings por último, e remova os números altos (9999) no final.

    
por 20.03.2012 / 21:57
1

Com o benefício de alguns anos de desenvolvimento, sort -V on sort 8.26 produz apenas a saída desejada:

$ 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
    
por 26.09.2018 / 21:51