Classificar com base na terceira coluna

132

Estou enfrentando um enorme arquivo de 4 colunas. Gostaria de exibir o arquivo classificado no stdout com base em sua terceira coluna:

cat myFile | sort -u -k3

Isso é suficiente para executar o truque?

user1058398
fonte
4
Observe que você pode escrever isso como sort -u -k3 < myFile.
gerrit
6
Como sort -u -k3 myFile, até mesmo
Sebastian Graf

Respostas:

168
sort -k 3,3 myFile

exibiria o ficheiro classificados pelo 3 rd coluna assumindo que as colunas são separadas por sequências de espaços em branco (SPC caracteres ASCII e guia na localidade POSIX / C), de acordo com a ordem de classificação definido pela localidade actual.

Observe que os espaços em branco à esquerda estão incluídos na coluna (o separador padrão é a transição de um não em branco para um em branco), que pode fazer a diferença em locais onde os espaços não são ignorados para fins de comparação, use a -bopção para ignorar os espaços em branco principais.

Observe que é completamente independente do shell (todos os shells analisariam a mesma linha de comando, os shells geralmente não têm o sortcomando incorporado).

-k 3é classificar na porção das linhas começando com o 3 rd coluna (incluindo os espaços em branco à esquerda). No código de idioma C, porque os caracteres de espaço e tab são classificados antes de todos os caracteres imprimíveis, que geralmente fornecem o mesmo resultado que -k 3,3(exceto linhas que possuem um terceiro campo idêntico),

-ué reter apenas uma das linhas se houver várias que sejam classificadas de forma idêntica (é aí que a chave de classificação será igual (não é necessariamente o mesmo que ser igual )).

caté o comando para con gato enate. Você não precisa aqui.

Se as colunas forem separadas por outra coisa, você precisará da -topção para especificar o separador.

Arquivo de exemplo fornecido a

$ cat a
a c c c
a b ca d
a b  c e
a b c d

Com -u -k 3:

$ echo $LANG
en_GB.UTF-8

$ sort -u -k 3 a
a b ca d
a c c c
a b c d
a b  c e

As linhas 2 e 3 têm a mesma terceira coluna, mas aqui a chave de classificação é da terceira coluna até o final da linha, portanto, -umantém as duas. ␠ca␠dclassifica antes ␠c␠cporque os espaços são ignorados na primeira passagem no meu código do idioma, cadclassifica antes cc.

$ sort -u -k 3,3 a
a b c d
a b  c e
a b ca d

Acima, apenas um é retido para aqueles onde a terceira coluna está ␠c. Observe como aquele com ␠␠c(2 espaços à esquerda) é mantido.

$ sort -k 3 a
a b ca d
a c c c
a b c d
a b  c e
$ sort -k 3,3 a
a b c d
a c c c
a b  c e
a b ca d

Veja como a ordem a b c de a c c cé invertida. No primeiro caso, porque ␠c␠cclassifica antes ␠c␠d, no segundo caso, porque a chave de classificação é a mesma ( ␠c), a comparação de último recurso que compara as linhas em colocações completas a b c dantes a c c c.

$ sort -b -k 3,3 a
a b c d
a b  c e
a c c c
a b ca d

Depois que ignoramos os espaços em branco, a chave de classificação para as 3 primeiras linhas é a mesma ( c), portanto, elas são classificadas pela comparação do último recurso.

$ LC_ALL=C sort -k 3 a
a b  c e
a c c c
a b c d
a b ca d
$ LC_ALL=C sort -k 3,3 a
a b  c e
a b c d
a c c c
a b ca d

No código de idioma C, ␠␠cclassifica antes, ␠cpois há apenas uma passagem para lá, onde os caracteres (bytes únicos) são classificados com base no valor do ponto de código (onde o espaço tem um ponto de código menor que c).

Stéphane Chazelas
fonte
colunas são blankseparadas, que podem incluir outros caracteres, além de espaço e tabulação, dependendo da localidade.
jfs
1
Bom, +1. Você poderia explicar o que 3,3faz? Por que não apenas 3?
terdon
@terdon, veja a descrição expandida com exemplos.
Stéphane Chazelas
@JFSebastian, você está certo, resposta atualizada.
Stéphane Chazelas
Ah, para classificar apenas no dia 3, não no resto da linha, obrigado.
terdon
4

Se você entende "coluna" como no arquivo de texto (quarto caractere), então sim, sua solução deve funcionar (ou até mesmo sort -u -k3 myFilepara permitir sortexecutar algumas mágicas de economia de memória com acesso aleatório). Se você entende "coluna" como no banco de dados - toda uma entidade de dados seguida por um separador e largura variável da coluna, precisará de algo mais sofisticado, por exemplo, isso classifica ls -l por tamanho

      ls -l |awk '{print $5 " " $0;}'| sort -n | cut -d " " -f 2-

(que é equivalente a trivial, ls -lSmas serve bem ao exemplo.)

SF.
fonte
5
Não, por classificação padrão colunas estão em branco separados, eles não são colunas de caracteres, para classificar na coluna 3, a sintaxe seria: sort -k 1.3,1.3. ls -l | sort -k5,5npara classificar no tamanho.
Stéphane Chazelas
A awksolução é exatamente o que eu needed-- facilmente modificado para se adequar às exigências de classificação complexo
jchook
2
sort -g -k column_number 

é o comando certo para classificar qualquer lista com caracteres numéricos usando coluna específica

Jayant Kumar Jain
fonte
1
O uso de -k já foi abordado muito bem, portanto, seria útil se você explicasse como esse comando é diferente ou melhor. Talvez você também possa incluir números reais de colunas para responder à pergunta real do OP.
Jeff Schaller
Isso me levou a usar as páginas de manual: p "-g, --general-numeric-sort, compare de acordo com o valor numérico geral", que era o que eu precisava no meu caso.
Joels
1

Você pode usar a biblioteca awk Velour :

#!/usr/local/bin/velour -f
{
  q[NR] = $3
  z[NR] = $0
}
END {
  a_sort_by(q, z)
  io_puts(q)
}
Steven Penny
fonte
0
$ sort -k 1.3,1.3 myfile

Classificará seu arquivo myfile na terceira coluna se o seu arquivo não tiver nenhum separador.

$ cat myfile 
ax5aa 
aa3ya 
fg7ds 
pp0dd 
aa1bb

$ sort -k 1.3,1.3 myfile 
pp0dd 
aa1bb
aa3ya 
ax5aa 
fg7ds 

página de manual do tipo:

[...] -k, --key = POS1 [, POS2] inicia uma chave no POS1 (origem 1), termina-a no POS2 (final da linha padrão) [...] POS é F [.C] [ OPTS], onde F é o número do campo e C a posição do caractere no campo; ambos são de origem 1. Se nem -t nem -b estiver em vigor, os caracteres em um campo serão contados desde o início do espaço em branco anterior. OPTS é uma ou mais opções de pedido de uma letra, que substituem as opções globais de pedido dessa chave. Se nenhuma tecla for fornecida, use a linha inteira como chave.

Com --key = 1.3,1.3, você disse que havia apenas um campo (a linha inteira) e que estava comparando a posição do terceiro caractere desse campo.

Franck
fonte