gdb
gdb

Reputation: 7809

Ascii/Hex convert in bash

I'm now doing it this way:

[root@~]# echo Aa|hexdump -v
0000000 6141 000a                              
0000003
[root@~]# echo -e "\x41\x41\x41\x41"
AAAA

But it's not exactly behaving as I wanted,

the hex form of Aa should be 4161,but the output is 6141 000a,which seems not making sense.

and when performing hex to ascii,is there another utility so that I don't need the prefix \x ?

Upvotes: 69

Views: 219725

Answers (16)

F. Hauri  - Give Up GitHub
F. Hauri - Give Up GitHub

Reputation: 71047

Pure bash, without loop Ascii <-> Hex convertion

1. Ascii to Hexadecimal conversion in bash

Very quick and short:

string='Hello World.' oIFS="$IFS" IFS=$'\n'
printf '%02X\n' ${string//?/$'\n'\'&}; IFS="$oIFS"

Will produce:

48
65
6C
6C
6F
20
57
6F
72
6C
64
2E

Yes, in order to handle space, we have to play with $IFS.

1.1. Into an variable of type array:

string='Hello World.' oIFS="$IFS" IFS=$'\n'
printf -v string '%02X\n' ${string//?/$'\n'\'&}; IFS="$oIFS"
mapfile -t array  <<<${string%$'\n'}
echo ${array[@]@Q}
'48' '65' '6C' '6C' '6F' '20' '57' '6F' '72' '6C' '64' '2E'

1.2. Better into a function to populate an array:

In a function, we could localize $IFS, things become a little simplier.

ascii2hex() {
    local _varname=$1 _string=${*:2} IFS=$'\n'
    printf -v _string '%02X\n' ${_string//?/$'\n'\'&}
    mapfile -t "$_varname" <<<${_string%$'\n'}
}
ascii2hex myArray 'Hello world!'
echo ${myArray[@]@Q}
'48' '65' '6C' '6C' '6F' '20' '77' '6F' '72' '6C' '64' '21'

Note: as function use ${*:2} as source string, space don't need to be quoted:

ascii2hex myArray Hello world!
echo ${myArray[@]@Q}
'48' '65' '6C' '6C' '6F' '20' '77' '6F' '72' '6C' '64' '21'

2. Hexadecimal to Ascii conversion in bash

Simply:

printf '%b' ${myArray[@]/#/\\x}
Hello world!

2.1. Then into a variable:

printf -v string '%b' ${myArray[@]/#/\\x}
echo $string
Hello world!

2.2. Into a function to define a variable

hex2ascii() {
    local _array=(${*:2})
    printf -v "$1" '%b' ${_array[@]/#/\\x}
}
hex2ascii mystring ${myArray[@]}
echo "$mystring"
Hello world!

Upvotes: 1

P1ratRuleZZZ
P1ratRuleZZZ

Reputation: 154

Finally got the correct thing

echo "Hello, world!" | tr -d '\n' | xxd -ps -c 200

Upvotes: 2

stelios
stelios

Reputation: 2855

I use:

> echo Aa | tr -d '\n' | xxd -p
4161

> echo 414161 | tr -d '\n' | xxd -r -p
AAa

The tr -d '\n' will trim any possible newlines in your input

Upvotes: 4

For single line solution:

echo "Hello World" | xxd -ps -c 200 | tr -d '\n'

It will print:

48656c6c6f20576f726c640a

or for files:

cat /path/to/file | xxd -ps -c 200 | tr -d '\n'

For reverse operation:

echo '48656c6c6f20576f726c640a' | xxd -ps -r

It will print:

Hello World

Upvotes: 23

baz
baz

Reputation: 1587

echo -n Aa | hexdump -e '/1 "%02x"'; echo

Upvotes: 1

jcomeau_ictx
jcomeau_ictx

Reputation: 38492

jcomeau@aspire:~$ echo -n The quick brown fox jumps over the lazy dog | python -c "print raw_input().encode('hex'),"
54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67
jcomeau@aspire:~$ echo -n The quick brown fox jumps over the lazy dog | python -c "print raw_input().encode('hex')," | python -c "print raw_input().decode('hex'),"
The quick brown fox jumps over the lazy dog

it could be done with Python3 as well, but differently, and I'm a lazy dog.

Upvotes: 0

scoombs
scoombs

Reputation: 11

SteinAir's answer above was helpful to me -- thank you! And below is a way it inspired, to convert hex strings to ascii:

for h in $(echo "4161" | sed "s/\(..\)/\1 /g"); do printf `echo "\x$h"`;done
Aa

Upvotes: 1

Vouze
Vouze

Reputation: 1784

With bash :

a=abcdefghij    
for ((i=0;i<${#a};i++));do printf %02X \'${a:$i:1};done

6162636465666768696A

Upvotes: 4

SteinAir
SteinAir

Reputation: 106

Text2Conv="Aa"
for letter in $(echo "$Text2Conv" | sed "s/\(.\)/'\1 /g");do printf '%x' "$letter";done

4161

The trick is using sed to parse the Text2Conv to format we can then seperate anf loop using for.

Upvotes: 2

childno͡.de
childno͡.de

Reputation: 4824

according to http://mylinuxbook.com/hexdump/ you might use the hexdump format parameter

echo Aa | hexdump -C -e '/1 "%02X"'

will return 4161

to add an extra linefeed at the end, append another formatter.

BUT: the format given above will give multiplier outputs for repetitive characters

$ printf "Hello" | hexdump -e '/1 "%02X"' 
48656C*
6F

instead of

48656c6c6f

Upvotes: 0

Thannoy
Thannoy

Reputation: 1

echo append a carriage return at the end.

Use

echo -e

to remove the extra 0x0A

Also, hexdump does not work byte-per-byte as default. This is why it shows you bytes in a weird endianess and why it shows you an extra 0x00.

Upvotes: -2

blogresponder
blogresponder

Reputation: 43

here a little script I wrote to convert ascii to hex. hope it helps:

echo '0x'"`echo 'ASCII INPUT GOES HERE' | hexdump -vC |  awk 'BEGIN {IFS="\t"} {$1=""; print }' | awk '{sub(/\|.*/,"")}1'  | tr -d '\n' | tr -d ' '`" | rev | cut -c 3- | rev

Upvotes: 1

Kundan Kumar
Kundan Kumar

Reputation: 114

I don't know how it crazy it looks but it does the job really well

ascii2hex(){ a="$@";s=0000000;printf "$a" | hexdump | grep "^$s"| sed s/' '//g| sed s/^$s//;}

Created this when I was trying to see my name in HEX ;) use how can you use it :)

Upvotes: 2

Random832
Random832

Reputation: 39090

The reason is because hexdump by default prints out 16-bit integers, not bytes. If your system has them, hd (or hexdump -C) or xxd will provide less surprising outputs - if not, od -t x1 is a POSIX-standard way to get byte-by-byte hex output. You can use od -t x1c to show both the byte hex values and the corresponding letters.

If you have xxd (which ships with vim), you can use xxd -r to convert back from hex (from the same format xxd produces). If you just have plain hex (just the '4161', which is produced by xxd -p) you can use xxd -r -p to convert back.

Upvotes: 77

bash-o-logist
bash-o-logist

Reputation: 6921

$> printf "%x%x\n" "'A" "'a"
4161

Upvotes: 26

Mikel
Mikel

Reputation: 25656

For the first part, try

echo Aa | od -t x1

It prints byte-by-byte

$ echo Aa | od -t x1
0000000 41 61 0a
0000003

The 0a is the implicit newline that echo produces.

Use echo -n or printf instead.

$ printf Aa | od -t x1
0000000 41 61
0000002

Upvotes: 33

Related Questions