Зручний розбір чисел із одиничними суфіксами?


10

Скажімо, у вас є дані з величиною у читаному для людини форматі, наприклад, вихід du -hта ви хочете надалі працювати над цими числами. Скажімо, ви хочете передавати свої дані через grep, щоб зробити підсумок підмножини цих даних. Ви робите це спеціально в багатьох системах, яких ви ніколи не бачили, і маєте лише мінімальні утиліти. Ви хочете перетворення суфіксів для всіх стандартних 10 ^ n суфіксів.

Існує утиліта gnu-linux для перетворення суфіксальних чисел у реальні числа в трубопроводі? Чи є у вас функція bash, написана для цього, або якась перл, яку, можливо, легко запам’ятати замість довжини заміни регулярних виразів або декількох кроків 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}'


Відповідні посилання:


2
Рідко потрібно використовувати grep and awk. Якщо ви використовуєте awk, тоді використовуйте awk. Просто додайте /200907/перед своїм кодом рядка, наприкладawk '/200907/{s+=$1} END {print s}'
Tony

Відповіді:


14

На основі моєї відповіді на одне з питань, з якими ви пов’язані:

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

Інший метод, який використовується:

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

для другого способу, що робити, якщо суфікс s?
джуарез

@djuarez: Який множник означає s?
Призупинено до подальшого повідомлення.

Ні, просто екстраполяція на інші одиничні випадки.
джуарез

@djuarez: Це не має сенсу. Ця відповідь стосується суфіксів SI, а не загальних одиниць (можливо, секунд?). Щоб розширити sedкоманду у моїй відповіді, ви додали б пункти для обробки додаткових суфіксів SI, як я показую в awkкоманді. s/T/ * 1000 G;наприклад, доданий на початку додав би терабайти, наприклад.
Призупинено до подальшого повідомлення.

3

Для цього можна використовувати регулярні вирази perl. Наприклад,

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

Це простий сценарій. Ви можете вважати це вихідним пунктом. Сподіваюся, це допоможе!


Дійсно, це один із способів. Я також знайшов stackoverflow.com/questions/2557649/… .
квасоля

3

Особисто я б просто не використовував прапор -h в першу чергу. Версія "читабельна для людей" округляє числа, які потрібно буде знову округлити при перетворенні назад, отримуючи ще менш точні. (Наприклад, 2.7MiB - це 2831155,2 байт. Що ви робили з іншими 0,8-м байтом ??!)

В іншому випадку ви можете попросити unitsперетворити MiB / GiB / KiB у просто "B", і це впорається з цим, але вам доведеться зробити щось на кшталт (якщо припустити, що ваш висновок вкладений, інакше cutвідповідним чином)

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

Добре зазначається, що є втрата точності. Доповнення введення до одиниць також працює .. але я виявив unitsвідсутність у моєму мінімальному дистрибутиві! Я думаю, що ми все зробили б по-різному, якби мали повний контроль над усім.
квасоля

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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.