在Bash命令行中将十六进制字符串转换为ASCII。

84

我有很多这种字符串,我希望找到一个将其转换为ASCII码的命令,我尝试过用 echo -eod,但是都没成功。

0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2

1
那看起来不像ASCII。ASCII未定义大于0x7f的值。 - Mark Byers
你的意思是它是二进制吗? - Kerby82
你的意思是使用int/binary而不是ASCII码吗?你展示的值超出了ASCII码的范围。 - P.P
1
你期望从你的示例字符串中得到什么? - Vaughn Cato
我期望得到一个可打印的字符串,但实际上不是...它应该是明文密码。但根据你所说的,我猜测它是加密或哈希过的(二进制版本)。 - Kerby82
7个回答

213

这对我有用。

$ echo 54657374696e672031203220330 | xxd -r -p
Testing 1 2 3$

-r 告诉它将十六进制转换为 ASCII,而不是其正常的相反方式

-p 告诉它使用纯文本格式。


4
在Mac上,使用Homebrew时,pbpaste | xxd -rp命令无法正常工作,但是pbpaste | xxd -r -p命令可以。 - Pysis
这怎么成为了被接受的答案?这不是使用 bash,而是使用 xxd - dagelf
1
小心!echo在打印任何内容时都会添加一个换行符。从技术上讲,这样更正确:printf "%s" "54657374696e672031203220330" | xxd -r -p,因为它不会添加换行符。 - Gabriel Staples
1
此外,对于任何想知道的人,以下是将二进制字符串(ASCII字符)转换为ASCII十六进制的方法:printf "%s" "Testing 1 2 3" | xxd -p。输出结果为:54657374696e67203120322033。如果你使用echo命令,则会在末尾得到多余的十六进制字符0a,它表示换行符\n。使用echo "Testing 1 2 3" | xxd -p的结果为54657374696e672031203220330a - Gabriel Staples

28

这段代码将把文本0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2转换为一串由11个等效值组成的字节流。这些字节将被写入标准输出。

TESTDATA=$(echo '0xA7.0x9B.0x46.0x8D.0x1E.0x52.0xA7.0x9B.0x7B.0x31.0xD2' | tr '.' ' ')
for c in $TESTDATA; do
    echo $c | xxd -r
done

正如其他人指出的那样,这不会生成可打印的ASCII字符串,因为指定的字节不是ASCII码。您需要提供更多关于如何获取此字符串的信息,以便我们帮助您解决问题。

工作原理:xxd -r将十六进制数据转换为二进制(类似于反向hexdump)。 xxd要求每行以该行上第一个字符的索引号开头(运行hexdump并查看每行如何以索引号开头)。在我们的情况下,由于每个执行只有一行,我们希望该数字始终为零。幸运的是,我们的数据已经在0x表示法中的每个字符之前具有零。小写字母x被xxd忽略,因此我们只需将每个0xhh字符传送到xxd,并让它完成其工作。

tr将句点转换为空格,使for正确分隔它。


对我来说,使用xxd --version不起作用=xxd V1.10 27oct98在新的Redhat Linux上(带有ksh)。我只得到一个§字符。 - shellter
这正是我得到的结果。数据不是文本,因此打印出来效果不太好。为了以可打印的形式查看它,请将我的代码放入一个bash函数中,例如danstest() { ... }。然后,调用该函数并将输出导向hexdump -C。这将逐字节地显示我的代码输出了什么数据。 - Dan Bliss
2
很酷。你只需要执行 ... done | hexdump -C,不需要任何函数。祝大家好运。 - shellter
2
需要使用xxd -r -p命令从"xxd V1.10 27oct98"获取字符串输出。 - JGurtz

18
你可以使用 xxd
$cat hex.txt
68 65 6c 6c 6f
$cat hex.txt | xxd -r -p
hello

10

你可以像这样使用。

$ cat test_file.txt
54 68 69 73 20 69 73 20 74 65 78 74 20 64 61 74 61 2e 0a 4f 6e 65 20 6d 6f 72 65 20 6c 69 6e 65 20 6f 66 20 74 65 73 74 20 64 61 74 61 2e

$ for c in `cat test_file.txt`; do printf "\x$c"; done;
This is text data.
One more line of test data.

我正在尝试解码游戏(Elite:Dangerous)中看起来像十进制数的神秘数据,这似乎可以工作(使用 \\ 代替 \x)。(: - SilverWolf

7
您提供的值是UTF-8编码值。在设置时,数组中包含以下内容:
declare -a ARR=(0xA7 0x9B 0x46 0x8D 0x1E 0x52 0xA7 0x9B 0x7B 0x31 0xD2)

将被解析以打印每个值的纯文本字符。

for ((n=0; n < ${#ARR[*]}; n++)); do echo -e "\u${ARR[$n]//0x/}"; done

使用 echo 命令将十六进制值转换为纯文本,输出结果包含可打印字符和一些不可打印字符,如下所示:

enter image description here

echo -e "\x<hex value here>"

使用 echo 命令将 UTF-8 值转换为纯文本:

echo -e "\u<UTF-8 value here>"

然后使用echo命令将八进制转换为纯文本:

echo -e "\0<octal value here>"

当你遇到了不熟悉的编码值时,花些时间查看常用编码方案的范围,以确定一个值属于哪种编码。从那里进行转换将会轻而易举。


4
echo -e 失败的原因可能是由于错误的转义。以下代码在类似于 your_program with arguments 的输出上对我很有效:
echo -e $(your_program with arguments | sed -e 's/0x\(..\)\.\?/\\x\1/g')

请注意,您的原始十六进制字符串包含非可打印字符。


2
制作一个像这样的脚本:
bash
#!/bin/bash

echo $((0x$1)).$((0x$2)).$((0x$3)).$((0x$4))

例子:

sh converthextoip.sh c0 a8 00 0b

结果:

192.168.0.11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接