91

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. Commented Oct 31, 2012 at 14:34
  • do you mean it's binary? 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... 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) Commented Oct 31, 2012 at 14:44

8 Answers 8

232

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.

Sign up to request clarification or add additional context in comments.

4 Comments

pbpaste | xxd -rp from Homebrew on Mac didn't work but pbpaste | xxd -r -p did ..........
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.
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.
echo -n text avoids the newline, shorter than printf.
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 Comments

not working for me with xxd --version = xxd V1.10 27oct98 on newish Redhat linux (with ksh). I just get one § char.
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.
cool. You can just do ` ... done | hexdump -C`, no function needed. Good luck to all.
needed to use xxd -r -p to get string output from "xxd V1.10 27oct98"
22

You can use xxd:

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

Comments

12

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 Comment

I'm trying to decode mysterious data from a game (Elite: Dangerous) that looks like decimal, this seems to work (with \\ instead of \x). (:
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.

Comments

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.

Comments

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

Comments

2

You can use xxd to easily convert pairs of hex digits into ASCII, as it conveniently ignores the 0x prefix and any garbage (non-hex digits) in the data. If you take advantage of bash's built-in redirection (with a "here string," you won't even need to use echo or printf.

All of these examples will produce the output you asked for:

  $ xxd -r -p <<< "0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2"
  $ xxd -r -p <<< "0xA7 0x9B 0x46 0x8D 0x1E 0x52 0xA7 0x9B 0x7B 0x31 0xD2"
  $ xxd -r -p <<< "A7.9B.46.8D.1E.52.A7.9B.7B.31.D2"
  $ xxd -r -p <<< "A79B468D1E52A79B7B31D2"
  • -r converts from hex to ASCII. It "reverses" the default, which would convert from ASCII to hex.
  • -p means the data is in "plain" format (see below for the fancier default format).
  • <<< redirects the data to become the input to the xxd command.

Because you shouldn't trust the Internet:

If you want to convince yourself that this works correctly, you can pipe the output back into xxd, this time in "forward" mode, to convert it to the original hex:

  $ xxd -r -p <<< "A79B468D1E52A79B7B31D2" | xxd -p
    a79b468d1e52a79b7b31d2

For fancier output, you can remove the -p:

  $ xxd -r -p <<< "A79B468D1E52A79B7B31D2" | xxd -g 1
    00000000: a7 9b 46 8d 1e 52 a7 9b 7b 31 d2                 ..F..R..{1.

Each line of output starts with the offset in hex, followed by the hex data grouped one byte at a time (that's the -g 1 option), and ending with the printable ASCII characters.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.