O comando GNU sort não está classificando palavras de comprimentos diferentes com prefixos comuns corretamente para mim, mas apenas ao usar um delimitador de campo para classificar um dos vários campos.
Aqui está o comportamento de classificação correto e esperado sem usar delimitadores de campo:
$ cat /tmp/test0
b
c
ant
a
bcd
bc
cn
$ sort /tmp/test0
a
ant
b
bc
bcd
c
cn
Observe que, para todas as palavras com um prefixo de string comum, a palavra mais curta é classificada antes da palavra mais longa. Por exemplo, a
é antes ant
, b
é antes , bc
é antes bcd
, etc. Esta é a maneira padrão e aceita de classificação de strings em inglês, por exemplo, em um dicionário.
No entanto, esse comportamento de classificação muda quando você tenta classificar dados tabulares (como um arquivo CSV) e classificar em uma das colunas. Aqui está o que parece:
$ cat /tmp/test1
b,foo
c,bar
ant,baz
a,foo
bcd,ty
bc,pe
cn,cn
$ sort /tmp/test1 -t, -k1
a,foo
ant,baz
bcd,ty
bc,pe
b,foo
c,bar
cn,cn
Observe que as palavras com um prefixo comum a
e c
ainda estão sendo tratadas corretamente, mas strings com um prefixo comum b
não; bcd
classifica antes bc
classifica antes b
, tudo isso está incorreto! Este comportamento é estável; você sempre obtém o mesmo resultado. Estou enfrentando exatamente o mesmo problema em um arquivo CSV muito maior e os erros de classificação são deterministicamente aleatórios, se isso faz sentido.
Eu tentei vários sinalizadores sort
e nenhum funcionou para corrigir esse comportamento. -d
e -s
não funciona. Isso está no GNU coreutils 9.4, pelo que vale a pena.
Então, isso é apenas um bug do sort
comando? De alguma forma, estou usando-o incorretamente? Há algo melhor que eu possa fazer para classificar o CVS por palavras na primeira coluna?
É a maneira como sua localidade atual define regras de agrupamento/classificação que está causando isso e como
-kN
usa o campoN
até o final da linha ao comparar linhas, não apenas o campoN
(e algumas localidades serão classificadasbc,pe
antesb,foo
se ignorarem as vírgulas).Use
-k1,1
para usar apenas esse campo específico ou especifique a localidade "C" e você deverá obter os resultados esperados:A resposta é que, apesar de alguns exemplos de uso online em contrário, o
-k
sinalizador leva DOIS parâmetros, portanto precisa ser escrito como-k 1,1
. Caso contrário, com-k 1
, ele não receberá um número de campo de parada e, portanto, apenas percorrerá a linha inteira. Portanto, o comportamento de classificação anômalo é na verdade causado pela representação UTF-8 do,
delimitador caindo em algum lugar entre os outros caracteres ASCII.Obrigado aos comentários de Stéphane Chazelas acima.
De acordo com o comentário de Stéphane Chazelas você está classificando toda a linha e não apenas o primeiro campo. Com
LC_ALL=C
,
classificações antesc
: