Допустим, у вас есть данные с количествами в удобочитаемом формате, например, вывод du -h
, и хотите продолжить работу с этими числами. Допустим, вы хотите передать свои данные через grep, чтобы произвести суммирование подмножества этих данных. Вы делаете это специальным образом на многих системах, которые никогда раньше не видели, и используете только минимальные утилиты. Вам нужны преобразования суффиксов для всех стандартных суффиксов 10 ^ n.
Существует ли утилита gnu-linux для преобразования суффиксированных чисел в действительные числа в конвейере? У вас есть функция bash, написанная для этого, или какой-нибудь Perl, который можно легко запомнить, вместо длины замены регулярных выражений или нескольких шагов 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}'
Соответствующие ссылки:
Основываясь на моем ответе на один из вопросов, с которыми вы связались:
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
Лично я бы вообще не использовал флаг -h. В «удобочитаемой» версии округляются числа, которые необходимо будет снова округлить при обратном преобразовании, что становится еще менее точным. (Например, 2,7 МБ - это 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}'
Для этого вы можете использовать регулярные выражения 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;
}
Это простой сценарий. Вы можете считать это отправной точкой. Надеюсь, это поможет!
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"