How to convert hex to ASCII characters in the Linux shell?
echo -n 5a | perl -pe 's/([0-9a-f]{2})/chr hex $1/gie'
Note that this won't skip non-hex characters. If you want just the hex (no whitespace from the original string etc):
echo 5a | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie'
Also, zsh
and bash
support this natively in echo
:
echo -e '\x5a'
Conversion hex string into ascii in bash command line
This worked for me.
$ echo 54657374696e672031203220330 | xxd -r -p
Testing 1 2 3$
-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.
How to convert hex to ASCII while preserving non-printable characters
xxd
expects two characters per byte. One A
is invalid. Do:
printf '%02X' 10 | xxd -r -p | xxd -p
How to convert hex to ASCII while preserving non-printable characters
Use xxd
. If your input has one character, pad it with an initial 0
.
ASCII does not preserve non-printable characters
It does preserve any bytes, xxd
is the common tool to work with any binary data in shell.
Is it possible to preserve these characters somehow?
Yes - input sequence of two characters per byte to xxd
.
convert hex characters in a file to ASCII using a shell script
It doesn't work because printf
used in bash isn't the same as in sh. For a quick fix, simply replace #!/bin/sh
by #!/bin/bash
. As long as you don't care about full compliance with /bin/sh
, it may be an easy solution.
However, if you really want to use the sh
interpreter, then use something like:
/bin/echo -e "\x40"
Ascii/Hex convert in bash
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.
bash ascii to hex
$ str="hello"
$ hex=$(xxd -pu <<< "$str")
$ echo "$hex"
6C6C6568A6F
Or:
$ hex=$(hexdump -e '"%X"' <<< "$str")
$ echo "$hex"
6C6C6568A6F
Careful with the '"%X"'
; it has both single quotes and double quotes.
How does this script work to convert the hex to ascii?
if we give ./hexToASCII 505152
then in line 1:hex="$1"
will be hex="505152"
From the next line:
for i in $(awk -v len=$(expr "$hex" : '.*') 'BEGIN {for(i=1;i<len;i=i+2) print i;}')
if we take expression by expression then :
$(expr "$hex" : '.*')
will give the length of the expression. awk -v len
will assign the length to the variable len
.
Int the following line:
for(i=1;i<len;i=i+2) print i;
it will print the values 1,3,5 which will be taken by the main loop for i in $(...)
and will start executing the loop for values of i (i.e 1,3,5)
Consider the next line:
awk -v d=$(printf "ibase=16\n%s\n" $(echo $hex|cut -c$i-$(expr $i + 1)) | bc) 'BEGIN {printf("%c",d);}'
In this line,
echo $hex|cut -c$i-$(expr $i + 1)
During the first execution of the loop, value of i will be 1 and as a result the expression will become echo $505152|cut -c1-2
and outputs 50(cut column1 and column2). It will be printed in
printf("%c",50)
to the ascii P.
This will continue for other values of i, resulting in cutting the expression 505152 to 50,51,52 and printing the corresponding ASCII.
In short this script, finds the length of the hex, cut (seperate) it by a multiple of 2 and prints ascii of each piece.
Replace HEX characters (\x20) from string with ASCII space
To only replace \x20
and nothing else use sed
:
sed 's/\\x20/ /g' <<< "$output"
or
yourCommand | sed 's/\\x20/ /g'
To replace all escape sequences use echo -n
(as kvantour already pointed out) or even better, the more portable printf %b
which can also assign directly to variables without using $()
:
printf -v output %b "$output"
In Unix shell, how to convert from hex string to stdout bytes in machine-endian order
What about this —
$ echo 00: 0123456789abcdef | xxd -r | xxd -g 8 -e | xxd -r | od -tx1
0000000 ef cd ab 89 67 45 23 01
0000010
According to man xxd
:
-e
Switch to little-endian hexdump. This option treats byte groups as words in little-endian byte order. The default grouping of
4
bytes may be changed using-g
. This option only applies to hexdump, leaving the ASCII (or EBCDIC) representation unchanged. The command line switches-r
,-p
,-i
do not work with this mode.-g bytes | -groupsize bytes
Separate the output of every bytes bytes (two hex characters or eight bit-digits each) by a whitespace. Specify
-g 0
to suppress grouping. Bytes defaults to2
in normal mode,4
in little-endian mode and1
in bits mode. Grouping does not apply to postscript or include style.
Related Topics
Mount Smb/Cifs Share Within a Docker Container
Are There Any Standard Exit Status Codes in Linux
Convert Dos Line Endings to Linux Line Endings in Vim
How to Install Latest Version of Git on Centos 8.X/7.X/6.X
How to Quickly Sum All Numbers in a File
How to Make an Executable Elf File in Linux Using a Hex Editor
"/Usr/Bin/Ld: Cannot Find -Lz"
How to Search and Replace Using Grep
How to Split CSV Files as Per Number of Rows Specified
Compiling C++ on Remote Linux Machine - "Clock Skew Detected" Warning
Format and Then Convert Txt to CSV Using Shell Script and Awk
How to Test If a Variable Is a Number in Bash
Environment Variable Substitution in Sed
The 'Eval' Command in Bash and Its Typical Uses
How to Permanently Export a Variable in Linux
Setting Environment Variables in Linux Using Bash