Pratica analisi dei numeri con suffissi unitari?


10

Supponiamo che tu abbia dati con quantità in formato leggibile dall'uomo, come l'output di du -h, e desideri operare ulteriormente su quei numeri. Diciamo che vuoi reindirizzare i tuoi dati attraverso grep per fare una somma di un sottoinsieme di quei dati. Lo fai ad-hoc su molti sistemi che non hai mai visto prima e hai solo utilità minime. Desideri conversioni di suffissi per tutti i suffissi 10 ^ n standard.

Esiste un'utilità gnu-linux per convertire i numeri con suffisso in numeri reali all'interno di una pipeline? Hai una funzione bash scritta per fare questo, o un po 'di perl che potrebbe essere facile da ricordare, invece di una serie di sostituzioni regex o diversi passi 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}'


Riferimenti rilevanti:


2
Raramente è necessario utilizzare grep e awk. Se stai usando awk, allora usa awk. Basta aggiungere /200907/davanti al codice per riga, ad esawk '/200907/{s+=$1} END {print s}'
Tony

Risposte:


14

Sulla base della mia risposta a una delle domande a cui hai collegato:

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}'

Un altro metodo utilizzato:

sed 's/G/ * 1000 M/;s/M/ * 1000 K/;s/K/ * 1000/; s/$/ +\\/; $a0' | bc

per il secondo metodo, cosa succede se il suffisso è s?
Djuarez,

@djuarez: quale moltiplicatore rappresenta la s?
In pausa fino a ulteriore avviso.

Nessuno, estrapolando solo su altri casi di unità.
Djuarez,

@djuarez: Non ha alcun senso. Questa risposta riguarda i suffissi SI, non le unità generali (secondi, forse?). Per estendere il sedcomando nella mia risposta, dovresti aggiungere delle clausole per gestire i suffissi SI aggiuntivi come mostrato nel awkcomando. s/T/ * 1000 G;aggiunto all'inizio aggiungerebbe terabyte, per esempio.
In pausa fino a ulteriore avviso.

3

Puoi usare le espressioni regolari perl per fare questo. Per esempio,

$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;
}

Questa è una semplice sceneggiatura. Puoi considerarlo come punto di partenza. Spero che possa aiutare!


In effetti, questo è un modo. Ho anche trovato stackoverflow.com/questions/2557649/… .
fagioli

3

Personalmente, non userei la bandiera -h in primo luogo. La versione "leggibile dall'uomo" completa i numeri che dovranno essere nuovamente arrotondati quando si converte indietro, diventando ancora meno precisi. (Ad esempio, 2,7 MiB sono 2831155,2 byte. Cosa hai fatto con l'altro 0,8 di un byte ??!)

Altrimenti, puoi chiedere unitsdi convertire MiB / GiB / KiB in solo "B" e lo gestirà, ma dovresti fare qualcosa del genere (supponendo che il tuo output sia a schede, altrimenti in modo cutappropriato)

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

Ben notato, c'è una perdita di precisione. Anche l'integrazione dell'input per le unità funziona .. ma ho trovato unitsmancante sulla mia distribuzione minima! Penso che faremmo tutti diversamente se avessimo il pieno controllo di tutto.
fagioli

2
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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.