Hex to Binary conversion in bash
Asked Answered
D

4

21

I'm trying to convert a series of bytes from hex to bin using bash. but I keep getting (seemingly random) "(standard_in) 1: syntax error" replies from the following code:

for j in c4 97 91 8c 85 87 c4 90 8c 8d 9a 83 81
do
        BIN=$(echo "obase=2; ibase=16; $j" | bc )
        echo $BIN
done

I did a similar thing with dec to bin, which works perfectly fine:

for i in {0..120}
do
        KEYBIN=$(echo "obase=2; ibase=10; $i" | bc)
        echo $KEYBIN
done

Does anyone have an idea why it works with decimal, but not with hex? In my opinion the syntax is pretty much the same (unless I'm missing something really hard.)

Dysthymia answered 20/6, 2012 at 13:9 Comment(1)
Possible duplicate of linux shell scripting: hex string to bytesXymenes
A
24

BC is a bit sensitive to case for hex values, change to uppercase and it should work

for j in C4 97 91 8C 85 87 C4 90 8C 8D 9A 83 81
do
        BIN=$(echo "obase=2; ibase=16; $j" | bc )
        echo $BIN
done

Output:

11000100
10010111
10010001
10001100
10000101
10000111
11000100
10010000
10001100
10001101
10011010
10000011
10000001
Answerable answered 20/6, 2012 at 13:27 Comment(5)
so it really was a simple error. thank you for pointing this out, works like a charm.Dysthymia
glad to help, BC is a great tool with some quirks that you just have to know :-)Answerable
Does anybody know how to pad bc's output to a certain number of digits? This isn't needed in the example above, but just try the loop with a 00 as input.Shantung
have a look at the length function. "The value of the length function is the number of significant digits in the expression."Answerable
Here is an example with just one value: echo "obase=2; ibase=16; EF" | bcNicety
B
17

I came up with this:

printf converts to hex, xxd -r -p takes the ascii hex stream and makes it actual binary

dumping with hexdump to prove it worked...

$ printf "%016x" 53687091200 | xxd -r -p | hexdump -C
00000000  00 00 00 0c 80 00 00 00                           |........|
00000008

Further reading:

Beatup answered 22/11, 2019 at 16:20 Comment(3)
Works. However, xxd won't let me combine -r and -p into -rp, and I can live with that for now.Hanleigh
how very un-unix like, but it is what it is I guess. you could open an issue on github probably :-)Beatup
the answer is amazingAbeyta
D
7

Here's the script I use:

#!/bin/bash
# SCRIPT:  hex2binary.sh
# USAGE:   hex2binary.sh Hex_Number(s)
# PURPOSE: Hex to Binary Conversion. Takes input as command line
#          arguments.
#####################################################################
#                      Script Starts Here                           #
#####################################################################

if [ $# -eq 0 ]
then
    echo "Argument(s) not supplied "
    echo "Usage: hex2binary.sh hex_number(s)"
else
    echo -e "\033[1mHEX                 \t\t BINARY\033[0m"

    while [ $# -ne 0 ]
    do
        DecNum=`printf "%d" $1`
        Binary=
        Number=$DecNum

        while [ $DecNum -ne 0 ]
        do
            Bit=$(expr $DecNum % 2)
            Binary=$Bit$Binary
            DecNum=$(expr $DecNum / 2)
        done

        echo -e "$Number              \t\t $Binary"
        shift
        # Shifts command line arguments one step.Now $1 holds second argument
        unset Binary
    done

fi
Debug answered 20/6, 2012 at 13:31 Comment(2)
Caveats: The hex numbers must be preceded by 0x, and the HEX column actually lists decimal values. But thank you for offering a pure bash solution to a "How to ... in bash" question! Sometimes that's actually what people are looking for. You can't always depend on the presence of tools like bc.Problematic
the version of bash I am using (4.4.12) doesn't need to prefix the hex numbers. The script doesn't handle 0 correctly though, you want to replace $Binary with ${Binary:-0} in the last echo callBiogenesis
R
3

Try this:

for HEXBYTE in c4 97 91 8c 85 87 c4 90 8c 8d 9a 83 81
do
    BIN=$(echo "obase=2; ibase=16; ${HEXBYTE^^}" | bc )
    echo $BIN
done

Output:

11000100
10010111
10010001
10001100
10000101
10000111
11000100
10010000
10001100
10001101
10011010
10000011
10000001
Responsive answered 13/10, 2019 at 14:52 Comment(2)
There are other answers that provide the OP's question, and they were posted some time ago. When posting an answer see: How do I write a good answer?, please make sure you add either a new solution, or a substantially better explanation, especially when answering older questions.Stav
Accepted answer says uppercase is required and changes the input data. This answer keeps the data (that often is out of control) and instead uses ${j^^} to convert the data to uppercase, thus this is the better solution, but lacking in explanation.Edmon

© 2022 - 2024 — McMap. All rights reserved.