シェルスクリプトの2進数から16進数および10進数


20

シェルスクリプトでバイナリを16進数と10進数に、またはその逆に変換する必要があるコンテキストがあります。誰かが私にこのためのツールを提案できますか?


7
最近の回答を見て、「バイナリ」がバイナリ数バイナリファイルかを指定する必要があります
マナトワーク

回答:


39

純粋なbash(およびビルトイン)でバイナリからの変換を行うのはかなり簡単です:echoprintf

2進数から10進数

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

2進数から16進数

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

bashを単独で使用してバイナリに戻るのはやや複雑なので、その解決策に関する他の回答を参照することをお勧めします。


10進数から16進数はどうですか。
バンギ

2
@Bangi printf '%x\n' 10たとえば
クリスダウン

1
printf %dbin2dec に使用する意味は何ですか?$(( ... ))すでに小数の結果が得られます、それでecho十分です。
アンドレアコルベッリーニ

@AndreaCorbellini-個人設定。一般に、私はさまざまな理由(主に移植性)のprintf '%s\n' foo代わりにecho使用します。同じ理由で、ここでは使用しません。
クリスダウン

@ChrisDown:私はこの質問は明示的にBash(十分に実装されたビルトインを持っているecho)についてでしたが。私の悪い!
アンドレアコルベリーニ

16

バイナリでは、ベース2の数値ではなく、0を含む任意のバイト値を持つデータのようにバイナリデータを意味すると仮定します。

変換することから、バイナリ、od(標準)、 xxd(付属していますvim)、またはperlさんは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さん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パラメータを:

秘trickは、ベースについて明確にする必要があるということです。したがって、ibaseが2の場合、obaseを10に設定しても、バイナリの10は2なので、何もしません。したがって、16進表記を使用する必要があります。

したがって、2進数から10進数になります(obaseがAであることに注意してください)

2進数から10進数:

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

2進数から16進数:

$> 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
この2番目の例は間違っています-'F'は16ではなく15を基数になります(16進数の16はFではなく10です)。echo 'ibase=2;obase=F;1111どちら 10進数の15に等しいか試してください。16進数の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

数値をbase-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))

等々。

両方ksh93zshもサポートしています。

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

しかし、それに注意し、拡大したときに、$binary必要があります2#または16#あなたがストリップすることができますプレフィックスを(${binary#*#}

ksh93 以下もサポートしています:

printf "%..2d\n" 123

バイナリに変換します。


1

2進数から16進数への使用の場合:Linuxのxxdツールおよび2進数から10進数の場合には、qalculateツールを使用できます。

xxdタイプxxd --helpまたはman xxdLinuxのヘルプについて。


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

前の回答で述べたように、echoとprintfを使用して、Bashで次のようにBinary to DecimalおよびHexa Decimalを実行できます。ここでは、純粋なBashを使用して、10進数と16進数からバイナリに変換する方法を追加しています。

エコーを使用した2進数から10進数へ

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

printfを使用した16進数へのバイナリ

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

Bashのみを使用した整数10進数から2進数への変換

Bashのみを使用して、10進数を2進数に変換する場合は、次のようにします。

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のみを使用した16進数からバイナリへの変換

同様に、bashのみを使用した次のような16進数から2進数へ:

#!/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

16進数を渡す必要があります。

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.