Using ‘printf’ to Output Chars from ASCII Numbers

bashprintf

I've been trying to make printf output some chars, given their ASCII numbers (in hex)… something like this:

#!/bin/bash

hexchars () { printf '\x%s' $@ ;}

hexchars 48 65 6c 6c 6f

Expected output:
Hello

For some reason that doesn't work though. Any ideas?

EDIT:

Based on the answer provided by Isaac (accepted answer), I ended up with this function:

chr  () { local var ; printf -v var '\\x%x' $@ ; printf "$var" ;}

Note, I rewrote his answer a bit in order to improve speed by avoiding the subshell.

Result:

~# chr 0x48 0x65 0x6c 0x6c 0x6f
Hello
~# chr 72 101 108 108 111
Hello
~# chr {32..126}
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}

I guess the inverse of the chr function would be a function like…

asc () { printf '%d\n' "'$1"  ;}
asc A
65
chr 65
A

Or, if we want strictly hex variants…

chrx () { local var ; printf -v var '\\x%s' $@ ; printf "$var\n" ;}
ascx () { printf '%x\n' "'$1"  ;}

chrx 48 65 6c 6c 6f
Hello
ascx A
41

Thank you!

Best Answer

Oh, sure, just that it has to be done in two steps. Like a two step tango:

$ printf "$(printf  '\\x%s' 48 65 6c 6c 6f)"; echo
Hello

Or, alternatively:

$ test () { printf "$(printf  '\\x%s' "$@")"; echo; }
$ test 48 65 6c 6c 6f
Hello

Or, to avoid printing on "no arguments":

$ test () { [ "$#" -gt 0 ] && printf "$(printf  '\\x%s' "$@")"; echo; }
$ test 48 65 6c 6c 6f
Hello
$ 

That is assuming that the arguments are decimal values between 1 and 127 (empty arguments would be counted but will fail on printing).

Related Question