Classificando arquivos numericamente, incluindo números negativos

0

Eu tenho vários arquivos:

adenine-N1_B+1,70_A+0,00.pdb
adenine-N1_B+1,70_A-10,00.pdb
adenine-N1_B+1,70_A+10,00.pdb
adenine-N1_B+1,70_A-15,00.pdb
adenine-N1_B+1,70_A+15,00.pdb
adenine-N1_B+1,70_A-20,00.pdb
adenine-N1_B+1,70_A+20,00.pdb
adenine-N1_B+1,70_A-25,00.pdb
adenine-N1_B+1,70_A+25,00.pdb
adenine-N1_B+1,70_A-30,00.pdb
adenine-N1_B+1,70_A+30,00.pdb
adenine-N1_B+1,70_A-5,00.pdb
adenine-N1_B+1,70_A+5,00.pdb

Gostaria de ordenar numericamente para obter o seguinte:

adenine-N1_B+1,70_A-30,00.pdb
adenine-N1_B+1,70_A-25,00.pdb
adenine-N1_B+1,70_A-20,00.pdb
adenine-N1_B+1,70_A-15,00.pdb
adenine-N1_B+1,70_A-10,00.pdb
adenine-N1_B+1,70_A-5,00.pdb
adenine-N1_B+1,70_A+0,00.pdb
adenine-N1_B+1,70_A+5,00.pdb
adenine-N1_B+1,70_A+10,00.pdb
adenine-N1_B+1,70_A+15,00.pdb
adenine-N1_B+1,70_A+20,00.pdb
adenine-N1_B+1,70_A+25,00.pdb
adenine-N1_B+1,70_A+30,00.pdb

Existe um comando de classificação para fazer isso? Até agora, tenho o seguinte:

for i in $(ls *.pdb | sort -V); do echo $i; done
    
por wanlei 06.07.2018 / 17:41

1 resposta

0

tl; dr

ls *.pdb | sort -k 1.20g

(Sim, eu sei isto e mais; veja a seção de armadilhas abaixo).

Lógica de classificação

Uma classificação numérica geral ( sort -g ) é a que você quer, mas você deve especificar onde os números começam.

Seus exemplos são da seguinte forma:

adenine-N1_B+1,70_A-15,00.pdb
                   ^ the number starts here: character 20, always

Não há espaços em branco, portanto, sort simples considera o nome do arquivo inteiro como sendo apenas um campo. Você precisa de uma classificação numérica geral que funcione a partir do 20º caractere do 1º campo:

sort -k 1.20g

Você pode querer introduzir uma lógica mais complexa para isso. Por exemplo. se uma das entradas for bogonine-X3_B+1,00_A-12,00.pdb , seria bastante sensato decompor entradas como esta:

foo_bar_A+00,00.pdb
   ^   ^ field separators
^ first field starts here
        ^ third field starts here
         ^ the number starts here: field 3, character 2

e para classificar (por exemplo) de acordo com o primeiro campo, depois por esses números, assim:

sort -t '_' -k 1,1 -k 3.2g

(Compare esta resposta ).

Local

O local especificado pelo ambiente afeta a ordem de classificação. Pode-se encontrar conselhos para definir LC_ALL=C apenas no caso. Isso pode ou não ser o que você quer, dependendo se você quer tratar a última vírgula ( , ) como um separador decimal ou não (bem, você tem ,00 em cada entrada, então não deveria importar mas importa em geral).

Se você precisar alterar a localidade apenas para uma chamada específica de sort , esta é a maneira:

LC_ALL=C sort …

Armadilhas em várias abordagens

Isso é o que você tentou:

for i in $(ls *.pdb | sort -V); do echo $i; done

O comando é extremamente complicado, a parte interna faz basicamente o mesmo trabalho:

ls *.pdb | sort -V

Analisando a saída de ls não é uma boa ideia , embora seus nomes de arquivos de exemplo sejam bastante seguros, então você deve longe com isso. Note que você não precisa de ls :

for i in *.pdb; do echo "$i"; done | sort …

O problema com ls *.pdb é que você pode acertar o erro argument list too long (bem, não no seu exemplo, mas novamente: em geral). A sintaxe for i in *.pdb; … está imune.

Seus nomes de exemplo parecem seguros para serem usados com echo ( veja o problema geral com echo ). Eles não contêm caracteres especiais, então você não precisa de find … -print0 nem sort -z … etc.

    
por 06.07.2018 / 21:19

Tags