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


All times are GMT -5. The time now is 10:13 AM.