87

I have a lot of this kind of string and I want to find a command to convert it in ascii, I tried with echo -e and od, but it did not work.

0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2
5
  • 1
    That does not look like ASCII. ASCII is not defined for values greater than 0x7f.
    – Mark Byers
    Commented Oct 31, 2012 at 14:34
  • do you mean it's binary?
    – Kerby82
    Commented Oct 31, 2012 at 14:36
  • Do you mean int/binary instead of ASCII? The values you have shown are greater than ASCII range...
    – P.P
    Commented Oct 31, 2012 at 14:38
  • 1
    What would you expect to get for your example string? Commented Oct 31, 2012 at 14:41
  • i would expect a printable string but it is not...it should be a clear text password. But from what you said i guess is encrypted or hashed (binary version)
    – Kerby82
    Commented Oct 31, 2012 at 14:44

7 Answers 7

221

This worked for me.

$ echo -n 54657374696e672031203220330 | xxd -r -p
Testing 1 2 3$

echo -n prevents a newline from being added to the end

-r tells it to convert hex to ascii as opposed to its normal mode of doing the opposite

-p tells it to use a plain format.

4
  • 4
    pbpaste | xxd -rp from Homebrew on Mac didn't work but pbpaste | xxd -r -p did ..........
    – Pysis
    Commented Apr 27, 2019 at 4:10
  • 2
    Watch out! echo adds a newline char to the end of everything it prints. Technically, this is more correct: printf "%s" "54657374696e672031203220330" | xxd -r -p since it doesn't add the newline char. Commented Jun 22, 2023 at 3:19
  • 2
    Also, for anyone wondering, here's how to go from the binary string (ASCII chars) to ASCII hex: printf "%s" "Testing 1 2 3" | xxd -p. Output: 54657374696e67203120322033. If you do echo instead, you get the stray hex 0a at the end, which is the newling \n char. echo "Testing 1 2 3" | xxd -p results in 54657374696e672031203220330a. Commented Jun 22, 2023 at 3:21
  • 1
    echo -n text avoids the newline, shorter than printf.
    – Stefan L
    Commented Feb 7 at 11:26
28

This code will convert the text 0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2 into a stream of 11 bytes with equivalent values. These bytes will be written to standard out.

TESTDATA=$(echo '0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2' | tr '.' ' ')
for c in $TESTDATA; do
    echo $c | xxd -r
done

As others have pointed out, this will not result in a printable ASCII string for the simple reason that the specified bytes are not ASCII. You need post more information about how you obtained this string for us to help you with that.

How it works: xxd -r translates hexadecimal data to binary (like a reverse hexdump). xxd requires that each line start off with the index number of the first character on the line (run hexdump on something and see how each line starts off with an index number). In our case we want that number to always be zero, since each execution only has one line. As luck would have it, our data already has zeros before every character as part of the 0x notation. The lower case x is ignored by xxd, so all we have to do is pipe each 0xhh character to xxd and let it do the work.

The tr translates periods to spaces so that for will split it up correctly.

4
  • not working for me with xxd --version = xxd V1.10 27oct98 on newish Redhat linux (with ksh). I just get one § char.
    – shellter
    Commented Oct 31, 2012 at 19:25
  • That is exactly what I get too. The data is not text, so it does not print out very well. To see it in a printable form, put my code into a bash function, like danstest() { ... }. Then, call the function and pipe the output to hexdump -C. This will show you byte-for-byte what data is coming out of my code.
    – Dan Bliss
    Commented Nov 1, 2012 at 14:31
  • 2
    cool. You can just do ` ... done | hexdump -C`, no function needed. Good luck to all.
    – shellter
    Commented Nov 1, 2012 at 15:05
  • 2
    needed to use xxd -r -p to get string output from "xxd V1.10 27oct98"
    – JGurtz
    Commented Aug 16, 2020 at 6:48
20

You can use xxd:

$cat hex.txt
68 65 6c 6c 6f
$cat hex.txt | xxd -r -p
hello
0
11

You can use something like this.

$ cat test_file.txt
54 68 69 73 20 69 73 20 74 65 78 74 20 64 61 74 61 2e 0a 4f 6e 65 20 6d 6f 72 65 20 6c 69 6e 65 20 6f 66 20 74 65 73 74 20 64 61 74 61 2e

$ for c in `cat test_file.txt`; do printf "\x$c"; done;
This is text data.
One more line of test data.
1
  • I'm trying to decode mysterious data from a game (Elite: Dangerous) that looks like decimal, this seems to work (with \\ instead of \x). (:
    – SilverWolf
    Commented Oct 16, 2017 at 14:09
7

The values you provided are UTF-8 values. When set, the array of:

declare -a ARR=(0xA7 0x9B 0x46 0x8D 0x1E 0x52 0xA7 0x9B 0x7B 0x31 0xD2)

Will be parsed to print the plaintext characters of each value.

for ((n=0; n < ${#ARR[*]}; n++)); do echo -e "\u${ARR[$n]//0x/}"; done

And the output will yield a few printable characters and some non-printable characters as shown here:

enter image description here

For converting hex values to plaintext using the echo command:

echo -e "\x<hex value here>"

And for converting UTF-8 values to plaintext using the echo command:

echo -e "\u<UTF-8 value here>"

And then for converting octal to plaintext using the echo command:

echo -e "\0<octal value here>"

When you have encoding values you aren't familiar with, take the time to check out the ranges in the common encoding schemes to determine what encoding a value belongs to. Then conversion from there is a snap.

4

The echo -e must have been failing for you because of wrong escaping. The following code works fine for me on a similar output from your_program with arguments:

echo -e $(your_program with arguments | sed -e 's/0x\(..\)\.\?/\\x\1/g')

Please note however that your original hexstring consists of non-printable characters.

0
2

Make a script like this:

bash
#!/bin/bash

echo $((0x$1)).$((0x$2)).$((0x$3)).$((0x$4))

Example:

sh converthextoip.sh c0 a8 00 0b

Result:

192.168.0.11
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.