LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   [bash] ASCII to HEX and hex to ascii (https://www.linuxquestions.org/questions/programming-9/%5Bbash%5D-ascii-to-hex-and-hex-to-ascii-488357/)

////// 09-30-2006 08:01 PM

[bash] ASCII to HEX and hex to ascii
 
What kind of command should I use to translate ascii to hex in a bash script ? (and hex back to ascii)

TIA

/////

paulsm4 09-30-2006 08:30 PM

do you mean something like this?
Code:

echo 0x41 | awk '{printf "%c\n", $1}'
A

The other direction (like an "ord(char)" function), is much less straightforward. Here are a couple of interesting solutions:

http://devworld.apple.com/documentat...section_3.html

And here's yet another possibility:
Code:

echo A|hexdump
0000000 0a41
0000002

... or, equivalently ...
Code:

echo A|od -x
0000000 0a41
0000002


////// 09-30-2006 08:53 PM

Hi, yes something like that. Only but is that..
Code:

echo 0x41 | awk '{printf "%c\n", $1}'
0

..this doesn't work in my box ;)
awk -W version
GNU Awk 3.1.5
Code:

awk '{printf "%c\n", $1}' /root/Desktop/testfile # testfile contains 0x41
0

it woold be good if it worked with words, not just single letters.

Cheers

////

Edit: Thank you, I can use that hexdump, and that link is a nice one :)

spirit receiver 10-01-2006 07:48 AM

Quote:

Originally Posted by //////
..this doesn't work in my box ;)

Try the following instead (with Bash):
Code:

ada@barnabas:~> echo -e "\x41" | awk '{printf "%c\n", $1}'
A

Edit: Sorry, I guess this is nonsense.

ghostdog74 10-01-2006 08:50 AM

alternative in Python:

ascii to hex:

Code:

#!/usr/bin/python
hex(ord('a'))

output:
'0x61'

hex to ascii
Code:

import binascii
binascii.a2b_hex("61")

output:
'a'

spirit receiver 10-01-2006 09:12 AM

... and I just learned that there's a package named uni2ascii which does the following:
Code:

ada@barnabas:~> echo "ABCDE" | uni2ascii -Bsepq
\x0041\x0042\x0043\x0044\x0045
ada@barnabas:~> echo "ABCDE" | uni2ascii -Bsepq | ascii2uni -Bq
ABCDE


////// 10-01-2006 09:55 AM

Quote:

Originally Posted by spirit receiver
... and I just learned that there's a package named uni2ascii which does the following:
Code:

ada@barnabas:~> echo "ABCDE" | uni2ascii -Bsepq
\x0041\x0042\x0043\x0044\x0045
ada@barnabas:~> echo "ABCDE" | uni2ascii -Bsepq | ascii2uni -Bq
ABCDE


Thanks guys, that uni2ascii is a good one, just compiled it and it does its job nicely.

osor 10-01-2006 11:18 AM

There's a nice utility that comes with Vim called xxd. It is script-friendly, and (unlike od or hexdump) has the ability to go back and forth (with the revert option).

For example, you could have something like:
Code:

... | xxd -g 1 -c 1 | awk ...
Where there are three fields you can access in awk. $1 is the offset (in hex), $2 is the two-digit hex representation of a byte, and $3 is the ASCII representation of the byte (or just a period for nonprintable characters).

For going back, just do something like:
Code:

... | xxd -p -s -
The only formatting restrictions on the input is that single bytes appear together as two-digit numbers. It doesn't care about formatting or whitespace (the -p is for plain).

I guess xxd's not as portable as hexdump or od, but it is probably more portable than uni2ascii (i.e., is more likely to be found installed on a *nix machine than uni2ascii).

////// 10-01-2006 11:44 AM

Quote:

Originally Posted by osor
I guess xxd's not as portable as hexdump or od, but it is probably more portable than uni2ascii (i.e., is more likely to be found installed on a *nix machine than uni2ascii).

Thats true, but I'm not that concerned about portability, (I'm using slax based Back|Track and adding modules is easy) and I'm not doing anything really important, just learning to write my own snort rules and I was getting tired to visit online hex translators ;)

But anyways, that ascii2hex is working nicely with my script so thanks again.

Code:

slax ~ # /root/Desktop/trans 'Hello there !'
48 65 6C 6C 6F 20 74 68 65 72 65 20 21

:)

gsm123 06-14-2010 06:48 PM

Another awk alternative with more than one character
 
Code:

echo -e "\x41\x20\x42\x20\x43" | awk '{printf "%s\n", $_}'
gives

Quote:

A B C

SPF 05-13-2013 09:31 AM

What if your string is:
48656C6C6F2074686572652021

And you don't have perl, python, xxd or uni2ascii?
And you are not allowed to install it.

How can you convert it?

Or course I could always write a loop and read it in pairs:

Code:

#!/bin/bash
function hex2string () {
  I=0
  while [ $I -lt ${#1} ];
  do
    echo -en "\x"${1:$I:2}
    let "I += 2"
  done
}
hex2string "48656C6C6F2074686572652021"


David the H. 05-15-2013 02:26 PM

Hex to ascii is dead easy; bash can do it internally, if they're properly formatted. Just use "echo -e", printf's %b format token, or the $'..' quoting form. See the sections on QUOTING and the echo built-in in the bash man page for full details on what these options can expand.

So in post #10 above, the awk command is actually completely superfluous. The characters are converted by echo before they even reach it.

As for the reverse direction, there's no built-in way to do it, so see the above. I've also used uniname before to get the hex codes of a string of characters.

Edit: Example use for the string in #9:

Code:

$ hexchars=( 48 65 6C 6C 6F 20 74 68 65 72 65 20 21 )
$ ( IFS='' ; printf '%b\n' "${hexchars[*]/#/\x}" )
Hello there !

I used a '(..)' subshell in order to keep the IFS setting local. It's needed in order to print the '*' expansion without spaces between each entry. Changing '*' to '@' would print every character on a separate line.

peetaur 06-02-2013 04:50 PM

You guys with awk are silly... your awk is not doing anything at all. Sorry to point that out. :P

Code:

$ echo -e "\x41\x20\x42\x20\x43" |cat
A B C
$ echo -e "\x41\x20\x42\x20\x43" | awk '{printf "%s\n", $_}'
A B C


es131245 03-20-2014 10:21 AM

Code:

#!/bin/sh
echo -e "\x41\x20\x42\x20\x43" | cat
echo -e "\x41\x20\x42\x20\x43" | awk '{printf "%s\n", $_}'
exit

Code:

"try.sh" 25 lines, 893 characters
\x41\x20\x42\x20\x43
awk: illegal field $(), name "_"
 input record number 1, file
 source line number 1

Code:

uname -a
FreeBSD host.com 10.0-RELEASE FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014    root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64


suicidaleggroll 03-20-2014 12:43 PM

Quote:

Originally Posted by es131245 (Post 5138096)
Code:

#!/bin/sh
echo -e "\x41\x20\x42\x20\x43" | cat
echo -e "\x41\x20\x42\x20\x43" | awk '{printf "%s\n", $_}'
exit

Code:

"try.sh" 25 lines, 893 characters
\x41\x20\x42\x20\x43
awk: illegal field $(), name "_"
 input record number 1, file
 source line number 1

Code:

uname -a
FreeBSD y-es.ru 10.0-RELEASE FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014    root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64


Works fine for me with both bash and sh. It looks to me like you have an outdated version of awk that doesn't support "$_", but I have no experience with FreeBSD. I'm running GNU awk 3.1.8

es131245 03-20-2014 01:23 PM

awk -version
awk version 20121220 (FreeBSD)

strange. System is updated. So its a third side soft

mattthumper 05-11-2016 07:29 AM

SPF - Thanks!
 
Quote:

Originally Posted by SPF (Post 4950137)
What if your string is:
48656C6C6F2074686572652021

And you don't have perl, python, xxd or uni2ascii?
And you are not allowed to install it.

How can you convert it?

Or course I could always write a loop and read it in pairs:

Code:

#!/bin/bash
function hex2string () {
  I=0
  while [ $I -lt ${#1} ];
  do
    echo -en "\x"${1:$I:2}
    let "I += 2"
  done
}
hex2string "48656C6C6F2074686572652021"


SPF, almost 3 years to the day later, your reply/post is just what I needed!
Thanks, Matt

thedonco 05-08-2018 09:55 PM

I was trying to easily convert back and forth between C-syntax Hex and Ascii (used a lot in Arduino, because apparently that's a fun way to store web pages on embedded controllers), and stumbled upon this thread. It was useful to completing my task, so thought it worth giving back. If nothing else, when I need to do this for something else and misplace these little utils, perhaps my web search will bring me here. :p

The following scriptlettes should be rather light weight and only use fairly standard POSIX utils (od, sed, bash).

$ cat asc2hex
Code:

#!/bin/bash

while read line; do
        echo $line|od -An -tx1|sed 's/ /, 0x/g;s/^, //;s/$/,/'
done < "${1:-/dev/stdin}"

exit 0

$ cat hex2asc
Code:

#!/bin/bash

while read line; do
        echo -en `echo $line|sed 's/, 0x/\\\\x/g;s/^0x/\\\\x/;s/,$//'`
done < "${1:-/dev/stdin}"

exit 0

Example usage:
Code:

$ echo "Hello World!"|./asc2hex
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0a,

$ echo "Hello World!"|./asc2hex|./hex2asc
Hello World!

Alternatively, scriptlettes will also accept direct file as an option:
Code:

$ cat hello_world
Hello World!

$ ./asc2hex hello_world
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0a,

$ ./asc2hex hello_world|./hex2asc
Hello World!



All times are GMT -5. The time now is 05:15 PM.