如何在Linux shell中将十六进制转换为ASCII字符?

时间:2009-10-22 02:52:50

标签: linux bash shell encoding scripting

假设我有一个字符串5a

这是ASCII字母Z的十六进制表示。

我需要知道一个Linux shell命令,它将采用十六进制字符串并输出字符串所代表的ASCII字符。

所以,如果我这样做:

echo 5a | command_im_looking_for

我会看到一封孤零零的字母Z

Z

14 个答案:

答案 0 :(得分:79)

我曾经使用xxd

这样做
echo -n 5a | xxd -r -p

然后我意识到在Debian / Ubuntu中,xxd是vim-common的一部分,因此可能不存在于最小系统中。为了避免使用perl(imho也不是最小系统的一部分),我最终使用了sed,xargs和printf:

echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf

大多数情况下,我只想转换几个字节,这对于这些任务来说还可以。这个解决方案优于ghostdog74的优点是,它可以自动转换任意长度的十六进制字符串。使用xargs是因为printf不从标准输入读取。

答案 1 :(得分:57)

echo -n 5a | perl -pe 's/([0-9a-f]{2})/chr hex $1/gie'

请注意,这不会跳过非十六进制字符。如果你只想要十六进制(没有来自原始字符串的空格等):

echo 5a | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie'

此外,zshbashecho本地支持此内容:

echo -e '\x5a'

答案 2 :(得分:13)

你可以通过回声而不用其他东西。不要忘记添加“-n”,否则您将自动获得换行符:

echo -n -e "\x5a"

答案 3 :(得分:9)

Bash one-liner

echo -n "5a" | while read -N2 code; do printf "\x$code"; done

答案 4 :(得分:3)

取决于你获得“5a”的位置,你可以将\ x附加到它并传递给printf

$ a=5a
$ a="\x${a}"
$ printf "$a"
Z

答案 5 :(得分:2)

这是一个纯粹的bash脚本(因为printf是bash内置的):

#warning : spaces do matter
die(){ echo "$@" >&2;exit 1;}

p=48656c6c6f0a

test $((${#p} & 1)) == 0 || die "length is odd"
p2=''; for ((i=0; i<${#p}; i+=2));do p2=$p2\\x${p:$i:2};done
printf "$p2"

如果bash已经运行,这应该比启动新进程的任何其他解决方案更快。

答案 6 :(得分:2)

dc可以在数字基数之间转换:

$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$

答案 7 :(得分:2)

一些使用任意数量字节的python3单行。

解码十六进制(使用strip,这样就可以在stdin上添加换行符了):

$ echo 666f6f0a | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
foo

编码十六进制:

$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a

答案 8 :(得分:1)

echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"

答案 9 :(得分:0)

GNU awk 4.1

awk -niord '$0=chr("0x"RT)' RS=.. ORS=

请注意,如果您回显它,它将产生一个额外的空字节

$ echo 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a  00
          Y   Z  \0

而是使用printf

$ printf 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a
          Y   Z

另请注意,GNU awk默认生成UTF-8

$ printf a1 | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1
0000000 c2 a1

如果您正在处理ASCII以外的字符,那么您将会是 Base64对结果字符串进行编码,您可以使用-b

禁用UTF-8
echo 5a | sha256sum | awk -bniord 'RT~/\w/,$0=chr("0x"RT)' RS=.. ORS=

答案 10 :(得分:0)

与我的回答类似:Linux shell scripting: hex number to binary string

您可以使用相同的工具(使用ascii可打印字符而不是5a)来执行此操作:

echo -n 616263 | cryptocli dd -decoders hex

将产生以下结果:

abcd

答案 11 :(得分:0)

根据@Randal comment,您可以使用perl,例如

$ printf 5a5a5a5a | perl -lne 'print pack "H*", $_'
ZZZZ

以及其他方式:

$ printf ZZZZ | perl -lne 'print unpack "H*", $_'
5a5a5a5a

另一个文件示例:

$ printf 5a5a5a5a | perl -lne 'print pack "H*", $_' > file.bin
$ perl -lne 'print unpack "H*", $_' < file.bin
5a5a5a5a

答案 12 :(得分:0)

有一个简单的shell命令“ ascii”,

如果您使用Ubuntu,请

sudo apt install ascii

然后:

ascii 0x5a

将输出:

ASCII 5/10 is decimal 090, hex 5a, octal 132, bits 01011010: prints as `Z'
Official name: Majuscule Z
Other names: Capital Z, Uppercase Z

答案 13 :(得分:0)

您可以将此命令(python脚本)用于较大的输入:

echo 58595a | python -c "import sys; import binascii; print(binascii.unhexlify(sys.stdin.read().strip()).decode())"

结果将是:

XYZ

为了更加简单,请定义别名:

alias hexdecoder='python -c "import sys; import binascii; print(binascii.unhexlify(sys.stdin.read().strip()).decode())"'

echo 58595a | hexdecoder