Двійкові до шістнадцяткової та десяткової у сценарії оболонки


20

У мене є контекст, в якому мені потрібно перетворити двійкове в шістнадцятковий і десятковий, і на зворотному, у сценарій оболонки. Може хтось запропонує мені інструмент для цього?


7
Побачивши останні відповіді, можливо, вам слід вказати, чи означає «двійковий» значення двійкового номера чи двійкового файла .
манатура

Відповіді:


38

Перетворення з бінарного в чистий баш ( echoі printfє вбудованими) досить просто:

Двійкові до десяткових

$ echo "$((2#101010101))"
341

Двійкові до шістнадцяткової

$ printf '%x\n' "$((2#101010101))"
155

Повернутися до бінарного, використовуючи лише bash, є дещо складнішим, тому я пропоную вам побачити інші відповіді для вирішення цього питання.


як щодо десяткових до шістнадцяткових.
Бангі

2
@Bangi Просто роби printf '%x\n' 10, наприклад.
Кріс Даун

1
Який сенс використовувати printf %dдля bin2dec? $(( ... ))вже дає десятковий результат, echoдостатньо.
Андреа Корбелліні

@AndreaCorbellini - Особисті переваги. Взагалі я використовую printf '%s\n' fooзамість echoрізних причин (в основному портативності), з тієї ж причини, я не використовую це тут.
Кріс Даун

@ChrisDown: Я хоч це питання явно стосувався Bash (який має добре реалізований echoвбудований). Моє ліжко!
Андреа Корбелліні

16

Якщо припустити, що під двійковим, ви маєте на увазі двійкові дані як у даних з будь-яким можливим значенням байта, включаючи 0, а не базові 2 числа:

Для перетворення з виконуваного файлу, od(стандарт), xxd(поставляється з vim) або perl«s unpackприходить на розум.

od -An -vtu1 # for decimal
od -An -vtx1 # for hexadecimal

xxd -p # for hexa

perl -pe 'BEGIN{$\="\n";$/=\30};$_=unpack("H*",$_)' # like xxd -p

# for decimal:
perl -ne 'BEGIN{$\="\n";$/=\30;$,=" "}; print unpack("C*",$_)'

Тепер, щоб перетворити назад у двійкові, awk(стандартні) xxd -rабо perl's pack:

Від десяткового виходу зверху od -tu1чи perlвище:

LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'

Від гекса perlабо xxd -pвище:

xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'

13

Ви можете використовувати bc для цього, маніпулюючи параметрами ibaseта obase:

Хитрість полягає в тому, що вам потрібно чітко пояснювати основи. Отже, якщо ваш ibase дорівнює 2, то якщо ви встановите obase на 10, він нічого не зробить, оскільки 10 у двійковій системі - це 2. Отже, вам потрібно використовувати шістнадцяткову нотацію.

Тож двійкові до десяткових були б (дивіться, що обасе є A)

Двійкові до десяткових:

$> echo 'ibase=2;obase=A;11110001011010'|bc
15450

Двійкові до шестигранних:

$> echo 'ibase=2;obase=10000;11110001011010'|bc
3C5A

Якщо obaseспочатку змінити 'вихідну базу' , це має бути легше:

$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A

6
Цей другий приклад помилковий - 'F' буде базовою 15, а не 16 (десятковий 16 у шістнадцятковій частині становить 10, а не F). Спробуйте, echo 'ibase=2;obase=F;1111яка повинна дорівнювати десятковій 15, тобто. F в шістнадцятковій. Виходить як 10, що знаходиться в базі 15 (цифри 0-E). Крім того , легше , якщо ви вказати obase першої , наприклад: echo 'obase=16;ibase=2;1111'|bc. Без плутанини.
goldilocks

2
Зараз це найгірше. Після того, як ви встановите ibase, ви навіть повинні забезпечити введення в цій базі obase. Так у вашому прикладі було б echo 'ibase=2;obase=10000;11110001011010'|bc. Краще прислухайтеся до порад золотокрилих і скасуйте порядок - спочатку встановіть obase, потім ibase.
манатура

3

Якщо ви маєте на увазі перетворення чисел з базової-2 в 10 або 16 і назад, bcце стандартний інструмент для цього, як це вже згадувало psarossy .

decimal=123
binary=$(echo "obase=2;$decimal" | bc)
hex=$(echo "obase=16;ibase=2;$binary" | bc)

Деякі оболонки, як, наприклад, zshмають вбудовану підтримку перетворення бази в рамках своїх операторів арифметичного розширення:

decimal=123
binary=$(([##2]decimal))
hex=$(([##16]decimal))
hex=$(([##16]2#$binary))
decimal=$((2#$binary))

і так далі.

І те, ksh93і zshтакож підтримують:

typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'

Але зауважте, що при розширенні $binaryбуде встановлений 2#або 16#префікс (який ви можете зняти ${binary#*#}.

ksh93 також підтримує:

printf "%..2d\n" 123

перетворити на бінарне.


1

Для двійкового та шістнадцяткового використання: інструмент xxd у Linux та для двійкових до десяткових можна використовувати інструмент qalculate.

Довідка щодо типу xxd xxd --helpабо man xxdв Linux.


1

Ви можете використовувати PHP:

$ php -r 'printf("%b", 11);'
1011

Або Perl:

$ perl -e 'print unpack("B*", pack("c", 11))'
00001011

$ perl -e 'print unpack("B*", pack("C", 11))'
00001011

$ perl -e 'print unpack("B*", pack("W", 11))'
00001011

$ perl -e 'print unpack("B*", pack("n", 11))'
0000000000001011

$ perl -e 'print unpack("B*", pack("N", 11))'
00000000000000000000000000001011

Або POSIX Awk svnpenn / stdlib :

$ awklib 'BEGIN {print mt_basecon(1011, 2, 16)}'
B

$ awklib 'BEGIN {print mt_basecon(1011, 2, 10)}'
11

$ awklib 'BEGIN {print mt_basecon("B", 16, 2)}'
1011

$ awklib 'BEGIN {print mt_basecon(11, 10, 2)}'
1011

0

Як було сказано в попередній відповіді, ви можете зробити Binary to Decimal і Hexa Decimal, як показано нижче в Bash, використовуючи echo і printf. Я просто додаю тут, як перетворити з десяткової та шістнадцяткової в бінарну, використовуючи чистий Bash.

Двійкові до десяткової за допомогою відлуння

echo "$((2#101010101))"
341

Двійкові до шестидесяткових за допомогою printf

printf '%x\n' "$((2#101010101))"
155

Ціле число в двійкове перетворення з використанням лише Bash

Використовуючи лише Bash, якщо ви хочете перетворити десятковий у двійковий, ви можете це зробити так:

touch dec2bin && chmod +x "$_" && vim "$_"

А потім скопіюйте та вставте наступне:

#!/bin/bash
## converting decimal integer to binary, pass int as a parameter
num=$1;
dec2bin()
{   [ "$num" == "" ] && { printf "Error: Pass an integer\n"; exit 1; };
    op=2; ## Since we're converting to binary
    quo=$(( $num / $op)); rem=$(( $num % $op)); ## quotient and remainder
    remarray=(); ## array for putting remainder inside array
    remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{   [[ -n ${num//[0-9]/} ]] &&
        { printf "Error: $num is not an integer bruv!\n"; return 1;
        } || { dec2bin $num; }
}
main;

А потім спробуйте звідки ви зберегли:

./dec2bin 420
110100100

Ціле число потрібно додати !!

./dec2bin 420.py
420.py is not an integer bruv!

Шестнадцятковий до бінарного перетворення, використовуючи лише Bash

Аналогічно, шістнадцятковий до двійкового, як слід, використовуючи лише bash:

#!/usr/local/bin/bash
## converting hexadecimal to binary, pass hex as a parameter
hex=$1;
hex2bin()
{   [ "$hex" == "" ] && { printf "Error: Pass a hex\n"; exit 1; };
    op=2; num=$((16#$hex)); ## converting hex to integer
    quo=$(( $num/ $op)); rem=$(( $num% $op)); ## quotient and remainder
    remarray=(); remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{
[[ -n ${hex//[0-9,A-F,a-f]/} ]] &&
    { printf "Error: $hex is not a hex bruv!\n"; return 1;
    } || { hex2bin $hex; }
}
main;

Наприклад:

./hex2bin 1aF
110101111

Шістнадцятковий повинен бути переданий:

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.