Análise útil de números com sufixos unitários?

8

Digamos que você tenha dados com quantidades em formato legível, como a saída de du -h , e deseje operar ainda mais esses números. Digamos que você queira enviar seus dados pelo grep para fazer um somatório de um subconjunto desses dados. Você faz isso ad-hoc em muitos sistemas que nunca viu antes e tem apenas utilitários mínimos. Você quer as conversões de sufixo para todos os sufixos 10 ^ n padrão.

Existe um utilitário gnu-linux para converter os números com sufixo em números reais em um pipeline? Você tem uma função bash escrita para fazer isso, ou algum perl que pode ser fácil de lembrar, em vez de uma extensão de substituições de regex ou várias etapas sed?

38M     /var/crazyface/courses/200909-90147
2.7M    /var/crazyface/courses/200909-90157
1.1M    /var/crazyface/courses/200909-90159
385M    /var/crazyface/courses/200909-90161
1.3M    /var/crazyface/courses/200909-90169
376M    /var/crazyface/courses/200907-90171
8.0K    /var/crazyface/courses/200907-90173
668K    /var/crazyface/courses/200907-90175
564M    /var/crazyface/courses/200907-90178
4.0K    /var/crazyface/courses/200907-90179

| grep 200907 | <amazing suffix conversion> | awk '{s+=$1} END {print s}'

Referências relevantes:

por beans 18.02.2011 / 20:07

4 respostas

9

Com base na minha resposta em uma das perguntas que você vinculou:

awk '{
    ex = index("KMGTPEZY", substr($1, length($1)))
    val = substr($1, 0, length($1) - 1)

    prod = val * 10^(ex * 3)

    sum += prod
}
END {print sum}'

Outro método usado:

sed 's/G/ * 1000 M/;s/M/ * 1000 K/;s/K/ * 1000/; s/$/ +\/; $a0' | bc
    
por 18.02.2011 / 21:37
2

Você pode usar expressões regulares perl para fazer isso. Por exemplo,

$value = 0;
if($line =~ /(\d+\.?\d*)(\D+)\s+/) {
   $amplifier = 1024 if ($2 eq 'K');
   $amplifier = 1024 * 1024 if ($2 eq 'M');
   $amplifier = 1024 * 1024 * 1024 if ($2 eq 'G');
   $value = $1 * $amplifier;
}

Este é um script simples. Você pode considerá-lo como ponto de partida. Espero que ajude!

    
por 18.02.2011 / 20:16
2

Pessoalmente, eu não usaria o sinalizador -h em primeiro lugar. A versão "legível por humanos" arredonda os números que precisarão ser arredondados novamente quando você converter de volta, ficando ainda menos preciso. (Por exemplo, 2.7 MiB é 2831155.2 bytes. O que você fez com o outro 0.8 de um byte ??!)

Caso contrário, você pode pedir ao units para converter MiB / GiB / KiB para apenas "B" e ele vai lidar com isso, mas você teria que fazer algo como (supondo que sua saída seja tabulada, caso contrário cut apropriadamente)

{your output} | cut -f1 '-d{tab}' | xargs -L 1 -I {} units -1t {}iB B | awk '{s+=$1}END{printf "%d\n",s}'
    
por 18.02.2011 / 20:35
1
VALUE=$1

for i in "g G m M k K"; do
        VALUE=${VALUE//[gG]/*1024m}
        VALUE=${VALUE//[mM]/*1024k}
        VALUE=${VALUE//[kK]/*1024}
done

[ ${VALUE//\*/} -gt 0 ] && echo VALUE=$((VALUE)) || echo "ERROR: size invalid, pls enter correct size"
    
por 07.10.2013 / 16:35