Classificando linhas em um arquivo por um valor numérico enterrado dentro

6

Estou escrevendo um script Bash para testar erros de memória flash USB usando a ferramenta f3 . Eu tenho um texto como este (criado por grepping logs do programa f3read ):

2017-10-25_09:30:22/sdf.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdi.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_09:30:22/sdj.log:Data LOST: 2.35 MB (4822 sectors)
2017-10-25_09:30:22/sdn.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_09:30:22/sdo.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdp.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdq.log:Data LOST: 2.00 KB (4 sectors)
2017-10-25_14:37:03/sdb.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_14:37:03/sdc.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdd.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sde.log:Data LOST: 2.00 KB (4 sectors)
2017-10-26_09:17:59/sdf.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdg.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdh.log:Data LOST: 611.29 MB (1251918 sectors)
2017-10-26_09:17:59/sdi.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdl.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdo.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdp.log:Data LOST: 2.00 KB (4 sectors)
2017-10-26_09:17:59/sdq.log:Data LOST: 414.60 MB (849106 sectors)
2017-10-26_09:17:59/sdr.log:Data LOST: 65.29 MB (133712 sectors)
2017-10-26_09:17:59/sds.log:Data LOST: 5.00 KB (10 sectors)

Eu gostaria de classificar as linhas pelo número de setores defeituosos anotados no final da linha. Eu tentei usar sort , mas não sei como usar a opção --key para fazer o que eu quero.

Não consigo cortar as linhas primeiro, porque preciso que o nome da unidade (sda, sdb, etc) seja extraído para um relatório.

    
por unfa 15.11.2017 / 13:15

5 respostas

8

Use sort -V se essa opção estiver disponível

-V, --version-sort

natural sort of (version) numbers within text

$ <cmd> | sort -k5,5V
2017-10-25_09:30:22/sdq.log:Data LOST: 2.00 KB (4 sectors)
2017-10-26_09:17:59/sde.log:Data LOST: 2.00 KB (4 sectors)
2017-10-26_09:17:59/sdp.log:Data LOST: 2.00 KB (4 sectors)
2017-10-25_14:37:03/sdc.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdd.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdf.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdo.log:Data LOST: 3.00 KB (6 sectors)
2017-10-25_09:30:22/sdf.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdo.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdp.log:Data LOST: 4.00 KB (8 sectors)
2017-10-25_09:30:22/sdi.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_09:30:22/sdn.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_14:37:03/sdb.log:Data LOST: 5.00 KB (10 sectors)
2017-10-26_09:17:59/sds.log:Data LOST: 5.00 KB (10 sectors)
2017-10-26_09:17:59/sdg.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdi.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdl.log:Data LOST: 6.00 KB (12 sectors)
2017-10-25_09:30:22/sdj.log:Data LOST: 2.35 MB (4822 sectors)
2017-10-26_09:17:59/sdr.log:Data LOST: 65.29 MB (133712 sectors)
2017-10-26_09:17:59/sdq.log:Data LOST: 414.60 MB (849106 sectors)
2017-10-26_09:17:59/sdh.log:Data LOST: 611.29 MB (1251918 sectors)
    
por 15.11.2017 / 13:21
10

POSIXly, você pode fazer:

sort -t '(' -k2n < file

Isso define o separador de campo como ( e classifica o segundo campo (ou melhor, a parte da linha que inicia com o segundo campo) numericamente.

Alternativamente, você poderia manter o separador de campo padrão (a transição de um não-branco para um vazio), onde o campo th seria como " (12" e use:

sort -k5.3n < file

(isto é, digite numericamente na parte da linha que começa com o caractere 3 rd do campo th ).

Para empates, a ordem de classificação de último recurso entra em jogo, e é uma comparação lexical da linha completa (que convenientemente aqui lhe dará uma ordem cronológica).

Se você quisesse classificar os vínculos no nome da unidade, poderia usar:

sort -t '(' -k2n -k1.21

(segunda chave sendo a parte da linha que começa com o caractere 21 st , comparação lexical)

    
por 15.11.2017 / 13:22
3

Eu encontrei.

sort -n -t '(' -k2V

-n diz ao sort para ler valores numéricos nas strings

-t '(' diz para usar o caractere ( como delimitador de campo. Porque a palavra setores) é sempre a mesma depois, não afetará a ordem de classificação.

-k2V define uma chave personalizada, usando a segunda coluna - texto após o primeiro caractere ( - para classificação.

    
por 15.11.2017 / 13:22
3

Se a sua versão de classificação padrão não oferecer a opção -V, você poderá usar um programa de classificação alternativo msort. Permite o uso de uma opção híbrida :
A comparação híbrida é como uma comparação lexicográfica, exceto pelo fato de que cadeias de dígitos são tratadas como números.

Então, um trecho assim:

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
pl " Input data file $FILE:"
tail -v $FILE

pl " Expected output:"
tail -v $E

pl " Results:"
msort -q -j -l -n 5,5 -c hybrid $FILE |
tail -v

produz isso:

-----
 Input data file data1:
==> data1 <==
2017-10-26_09:17:59/sdf.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdg.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdh.log:Data LOST: 611.29 MB (1251918 sectors)
2017-10-26_09:17:59/sdi.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdl.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdo.log:Data LOST: 3.00 KB (6 sectors)
2017-10-26_09:17:59/sdp.log:Data LOST: 2.00 KB (4 sectors)
2017-10-26_09:17:59/sdq.log:Data LOST: 414.60 MB (849106 sectors)
2017-10-26_09:17:59/sdr.log:Data LOST: 65.29 MB (133712 sectors)
2017-10-26_09:17:59/sds.log:Data LOST: 5.00 KB (10 sectors)

-----
 Expected output:
==> expected-output1 <==
2017-10-25_09:30:22/sdn.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_14:37:03/sdb.log:Data LOST: 5.00 KB (10 sectors)
2017-10-26_09:17:59/sds.log:Data LOST: 5.00 KB (10 sectors)
2017-10-26_09:17:59/sdg.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdi.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdl.log:Data LOST: 6.00 KB (12 sectors)
2017-10-25_09:30:22/sdj.log:Data LOST: 2.35 MB (4822 sectors)
2017-10-26_09:17:59/sdr.log:Data LOST: 65.29 MB (133712 sectors)
2017-10-26_09:17:59/sdq.log:Data LOST: 414.60 MB (849106 sectors)
2017-10-26_09:17:59/sdh.log:Data LOST: 611.29 MB (1251918 sectors)

-----
 Results:
==> standard input <==
2017-10-25_09:30:22/sdi.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_09:30:22/sdn.log:Data LOST: 5.00 KB (10 sectors)
2017-10-25_14:37:03/sdb.log:Data LOST: 5.00 KB (10 sectors)
2017-10-26_09:17:59/sdi.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdl.log:Data LOST: 6.00 KB (12 sectors)
2017-10-26_09:17:59/sdg.log:Data LOST: 6.00 KB (12 sectors)
2017-10-25_09:30:22/sdj.log:Data LOST: 2.35 MB (4822 sectors)
2017-10-26_09:17:59/sdr.log:Data LOST: 65.29 MB (133712 sectors)
2017-10-26_09:17:59/sdq.log:Data LOST: 414.60 MB (849106 sectors)
2017-10-26_09:17:59/sdh.log:Data LOST: 611.29 MB (1251918 sectors)

Alguns detalhes para o msort:

msort   sort records in complex ways (man)
Path    : /usr/bin/msort
Version : 8.53
Type    : ELF 64-bit LSB executable, x86-64, version 1 (SYS ...)
Help    : probably available with -h,--help
Repo    : Debian 8.9 (jessie) 
Home    : http://www.billposer.org/Software/msort.html (pm)

Em um sistema como:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30

Felicidades ... felicidades, drl

    
por 15.11.2017 / 13:44
3

Uma solução um pouco mais flexível extrai a contagem do setor, duplica-a no início da linha, classifica e, finalmente, remove a parte duplicada novamente:

sed 's/^.*(\([0-9]\{1,\} \)sectors)$/&/' |
  sort -n |
  cut -d ' ' -f 2-

Esta solução é mais flexível porque funciona para padrões arbitrários que identificam a chave de ordenação em cada registro.

    
por 15.11.2017 / 21:15

Tags