Неформатные строки размера диска - PullRequest
3 голосов
/ 09 декабря 2010

Есть ли какой-нибудь способ преобразовать строки типа 1K в 1000, 1M в 1000000 и т. Д. С помощью одной команды Bash? Я бы хотел избежать того, чтобы быть парнем в миллион и тридцать первым, чтобы создать для этого хакер из 10 строк или более 100 символов. Что-то вроде iso2int 5MB.

Редактировать: units -t '5MB' 'bytes работает, но этот инструмент недоступен. Существуют ли простые способы преобразования либо 5M или 5MB и аналогичных байтов?

Решение Макса было элегантным, но самый короткий эквивалент, который работал бы в моем случае, по крайней мере sed -e 's/b//i;s/k/*1000/i;s/m/*1000000/i;s/g/*1000000000/i;s/t/*1000000000000/i' | bc.

Ответы [ 2 ]

3 голосов
/ 09 декабря 2010

Как-то так?

$ echo "1K + 10M" | sed -e "s/K/*1024/g;s/M/*1024*1024/" | bc
10486784

Редактировать:

sed -e 's/t/kg/i;s/g/km/i;s/m/kk/i;s/k/*1000/ig;s/b//i' | bc
1 голос
/ 10 декабря 2010

Редактировать:

Мой первоначальный ответ просто глупо .Вот чистое решение Bash, основанное на макс талдыкиных sed / bc превосходный ответ .

s=21TB;(( $BASH_VERSINFO >= 4 ))&&s=${s^^};s=${s/B};s=${s/E/KP};s=${s/P/KT}; s=${s/T/KG};s=${s/G/KM};s=${s/M/KK};s=${s//K/*1024};printf "%'u\n" $((s))

Это длиннее, чем мой первоначальный однострочник, только в силу тогочто он включает в себя нечувствительность к регистру, в то время как последний этого не сделал (хотя мог и сделать функцию).Это только примерно вдвое больше по количеству символов, чем макс, если отрегулировать для эквивалентной функциональности.

Оригинал:

Вот чистое решение Bash:

В качестве функции (см. Ниже однострочник):

#!/bin/bash
# written by Dennis Williamson 2010-12-09
# for /4062349/neformatnye-stroki-razmera-diska
expandsi () {
    # set k to 1000 if that's your preference, p is a pattern to match unit chars
    local k=1024 p='E|P|T|G|M|K| '   # exa, peta, tera, giga, mega, kilo, bytes
    local b=$1 c e s=${p//|}         # s is the list of units
    (( $BASH_VERSINFO >= 4 )) && b=${b^^}  # toupper for case insensitivity
    b=${b%B*}                        # strip any trailing B from the input
    c=${b: -1}                       # get the unit character
    c=${c/%!($p)/ }                  # add a space if there's no unit char
    b=${b%@($p)*}                    # remove the unit character
    e=${s#*${c:0:1}}                 # index into the list of units
    # do the math, remove the single quote to omit the thousands separator
    printf "%'u\n" $((b * k**${#e}))
}

Для проверки функции:

testvals='1 22 333 4444 '
testvals+='4B 44B 1000B '
testvals+='1M 1MB 987MB '
testvals+='1K 23KB 1KB 100K '
testvals+='10G 10GB 3333G '
testvals+='3T 12PB '
# exabytes is pushing it for Bash's int capacity
# on my system, printf "%'u\n" -1 gives 18,446,744,073,709,551,615
testvals+='15EB '

for i in $testvals
do
    expandsi $i
done

Результаты:

1
22
333
4,444
4
44
1,000
1,048,576
1,048,576
1,034,944,512
1,024
23,552
1,024
102,400
10,737,418,240
10,737,418,240
3,578,781,499,392
3,298,534,883,328
13,510,798,882,111,488
17,293,822,569,102,704,640

Как и было обещано,наконец, однострочная версия:

$ b=200GB k=1024 p='E|P|T|G|M|K| ';s=${p//|} b=${b%B*};c=${b: -1};c=${c/%!($p)/ };b=${b%@($p)*};e=${s#*${c:0:1}};printf "%'u\n" $((b * k**${#e}))
214,748,364,800
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...