쉘 스크립트에서 이진수를 16 진수와 10 진수로


20

쉘 스크립트에서 바이너리를 16 진수 및 10 진수로 변환하거나 그 반대로 변환 해야하는 컨텍스트가 있습니다. 누군가 나를 위해 도구를 제안 할 수 있습니까?


7
최근 답변을 보면“binary”가 이진수 또는 이진 파일 인지 여부를 지정해야 합니다 .
manatwork

답변:


39

공정하게 변환 할 간단합니다 에서 순수 bash는 이진 ( echoprintf내장 명령입니다) :

이진수를 십진수로

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

이진수에서 16 진수

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

bash만으로 바이너리로 돌아가는 것은 다소 복잡하므로 이에 대한 해결책에 대한 다른 답변을 볼 것을 제안합니다.


십진수에서 16 진수는 어떻습니까?
Bangi

2
@Bangi 그냥하세요 printf '%x\n' 10.
Chris Down

1
printf %dbin2dec 에 사용하는 요점은 무엇입니까 ? $(( ... ))이미 10 진수 결과를 제공하면 echo충분합니다.
Andrea Corbellini 2013

@AndreaCorbellini-개인 취향. 일반적으로 다양한 이유로 (대부분 이식성) printf '%s\n' foo대신에 echo같은 이유로 사용하지 않습니다.
Chris Down

@ChrisDown : 나는이 질문이 Bash (잘 구현 된 echo내장 기능이 있음)에 대해 명시 적으로 있었지만 . 내 잘못이야!
Andrea Corbellini 2013

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또는 perlpack:

에서 소수점 출력에서 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

ibaseobase매개 변수 를 조작하여 bc를 사용할 수 있습니다 .

요령은 기지에 대해 명시 적으로해야한다는 것입니다. 따라서 ibase가 2 인 경우 obase를 10으로 설정하면 바이너리의 10이 2이므로 아무 것도 수행하지 않으므로 16 진 표기법을 사용해야합니다.

따라서 이진수를 십진수로 (obase가 A인지 확인하십시오)

이진수를 십진수로 :

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

이진수를 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
이 두 번째 예는 잘못되었습니다. 'F'는 16이 아니라 15가됩니다 (16 진 16 진수는 F가 아니라 10 임). 시도 echo 'ibase=2;obase=F;1111하는 해야 즉 진수 (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.
manatwork

3

base-2에서 10 또는 16으로 숫자를 변환하는 것을 의미하는 경우 psarossy에서bc 이미 언급 한 것처럼 표준 도구 입니다.

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

바이너리에서 16 진수로 사용하는 경우 : xxd 도구 (리눅스에서는 xxd 도구)에서 바이너리에서 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에서 다음과 같이 이진 대 십진수 및 헥사 십진수를 수행 할 수 있습니다. 순수 Bash를 사용하여 Decimal 및 16 진수를 바이너리로 변환하는 방법을 여기에 추가하고 있습니다.

echo를 사용하여 이진수를 10 진수로

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

printf를 사용하여 이진수를 16 진수로

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

Bash 만 사용하는 정수 10 진수를 이진수로 변환

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 만 사용하여 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.