在命令行上将字符串转换为十六进制

49

我正在尝试通过命令行以最高效的方式将“Hello”转换为十六进制格式的48 65 6c 6c 6f

我尝试使用printf和谷歌搜索,但是没有取得任何进展。

非常感谢您的帮助。

提前致谢。


什么操作系统?有很多“命令行”…… - Nemo
你看过这里吗:http://www.commandlinefu.com/commands/view/6066/convert-ascii-string-to-hex 和这里:http://stackoverflow.com/questions/2103698/dos-command-to-format-string-to-hex-value? - Mrchief
cmd 还是 bash? - Zimba
请参阅此处获取更多信息:https://dev59.com/nnE85IYBdhLWcg3wx2n2 - pdem
5个回答

102
echo -n "Hello" | od -A n -t x1

解释:

  • echo程序将向下一个命令提供字符串。
  • -n标志告诉echo在“Hello”末尾不生成新行。
  • od程序是“八进制转储”程序。(我们将提供一个标志告诉它以十六进制而不是八进制进行转储。)
  • -A n标志是--address-radix=n的简写形式,其中n是“none”的简写。如果没有这部分,命令将在左侧输出一个丑陋的数字地址前缀。这对于大型转储很有用,但对于短字符串来说是不必要的。
  • -t x1标志是--format=x1的简写形式,其中x是“十六进制”的简写,1表示1字节。
在ExplainShell.com上有更多关于此的详细信息:https://explainshell.com/explain?cmd=echo+-n+%22Hello%22+%7C+od+-A+n+-t+x1

3
好的,这个方法确实很有效。你是否知道如何去掉空格? - Eamorr
2
echo -n "Hello" | od -A n -t x1 | sed 's/^ *//' 的翻译内容为: - Tomas
5
我相信你的意思是执行以下命令: echo -n "Hello" | od -A n -t x1 | sed 's/ *//g' 该命令的作用是将字符串"Hello"转换为十六进制格式并去除空格。 - ndvo
1
'od' 不是内部或外部命令,也不是可运行的程序或批处理文件。 - Zimba
3
上述概述的解决方案和评论中提到的解决方案都没有考虑到某个工具在达到一定字符数时会产生的换行符。 - Tim Daubenschütz
显示剩余6条评论

16

如果您想要做到这一点并去除空格,您需要执行以下操作:

echo -n "Hello" | od -A n -t x1 | sed 's/ *//g'

管道中的前两个命令已经被@TMS在他的回答中解释得很清楚了,由@James编辑。最后一个命令与@TMS的评论不同,因为它是正确的并且已经被测试过。解释如下:
  • sed是一个stream editor。
  • ssubstitute命令。
  • /打开正则表达式——任何字符都可以使用。/是传统的,但对于处理XML或路径名等内容来说不太方便。
  • /或您选择的替代字符,关闭正则表达式并打开替换字符串。
  • / */中,*匹配前一个字符(在本例中是空格)的任何序列。
  • /或您选择的替代字符,关闭替换字符串。在这种情况下,替换字符串//为空,即删除匹配项。
  • g是执行此替换的选项,在每行上进行全局替换,而不仅仅是每行一次。
  • 引号使命令解析器不会混淆——整个序列作为第一个选项传递给sed,即一个sed脚本。

@TMS的想法(sed 's/^ *//')仅从每行开头删除空格(^匹配行的开头——在sed中称为“模式空间”)。

如果您还想删除换行符,则最简单的方法是追加

| tr -d '\n'

对于命令管道,使用|将之前处理过的流输入到该命令的标准输入中。其中tr是翻译命令,-d指定删除匹配的字符。引号中列出了您要匹配的字符列表 - 在这种情况下只有换行符(\n)。翻译只匹配单个字符,而不是序列。

sed在处理换行符时具有独特的缺陷。这是因为sed是最早的unix命令之一 - 它是在人们真正知道自己在做什么之前创建的。普遍存在的遗留软件使其无法修复。我知道这是因为我比unix还要老。

问题的历史起源是换行符是行分隔符而不是行的一部分的想法。因此,它被行处理实用程序剥离并由输出实用程序重新插入。问题在于,这样做对用户数据结构进行了假设,并在许多设置中施加了不自然的限制。 sed无法轻松地删除换行符是那种畸形思想造成痛苦的最常见的例子之一。

有可能使用sed删除换行符,只是我所知道的所有解决方案都使sed一次处理整个文件,这会导致处理非常大的文件时出现问题,从而破坏了流编辑器的目的。任何保留行处理的解决方案(如果可能的话)都将是多个管道的难以阅读的麻烦事。

如果您坚持使用sed,请尝试以下方法:

sed -z 's/\n//g'

-z选项告诉sed使用null作为行分隔符。

C中,字符串以null结尾。-z选项也是一种传统遗留,方便C程序员使用一个由C字符串填充的临时文件,不受换行符干扰。然后他们可以轻松读取和处理一个字符串。但是,早期关于使用案例的假设对用户数据施加了人为限制。

如果省略g选项,则此命令仅删除第一个换行符。使用-z选项,sed将整个文件解释为一行(除非文件中有零散的null),以null结尾,因此它可能无法处理大型文件。

您可能会想:

sed 's/^/\x00/' | sed -z 's/\n//' | sed 's/\x00//'

可能会起作用。第一条命令基于逐行处理,在每一行前放置一个空值,导致 \n\x00 结尾的每一行。第二条命令从每一行中删除一个换行符,现在由空值分隔 - 由于第一条命令,只会有一个换行符。所有多余的空值都会被保留。到目前为止还不错。这里破碎的想法是,管道将以逐行方式馈送最后一个命令,因为这就是流的构建方式。实际上,最后一个命令仅仅会删除一个空值,因为现在整个文件没有换行符,因此只有一行。

简单的管道实现使用中间临时文件,并且所有的输入都会被处理并提供给该文件。下一个命令可以在另一个线程运行,同时读取该文件,但它只会看到整个流(虽然不完整),并且没有意识到馈送文件的块边界。即使管道是内存缓冲,下一个命令也会将流视为整体。这个缺陷被不可避免地融入了 sed 中。

要使此方法起作用,您需要在最后一个命令上使用 g 选项,因此,它会在处理大文件时出现问题。

底线是:不要使用 sed 处理换行符。


“sed在处理换行符时表现独特愚钝。 [...] 它是在人们真正掌握这个东西之前创建的。”“什么?!”虽然听起来很过激,但你有权发表自己的看法。 - Cbhihe
一个通用的解决方案应该使用-v调用od,以避免重复字符被抑制。 - Martin

9

echo hello | hexdump -v -e '/1 "%02X "'


我的NAS(busybox)上没有“od”,但这个命令可以用“hexdump”代替。我还通过添加“| tr -d ' '”来删除空格。谢谢! - CodeShane
2
echo hello | hexdump -v -e '/1 "%02X"' 如果您不需要空格 - pdem
1
以下展示了如何将文本转换为十六进制,然后再将其转换回文本,而无需在十六进制值之间添加任何空格或换行符:echo -n hello | hexdump -v -e '/1 "%02X"' | xxd -r -p - smalers

1
进一步尝试后,一个可行的解决方案是去除“*”,因为在原始要求中只需简单地删除空格,如果需要替换实际字符,则“*”是不必要的,如下所示。
echo -n "Hello" | od -A n -t x1 | sed 's/ /%/g'

%48%65%6c%6c%6f

因此,我认为这是对原始问题的改进,因为现在该语句完全符合要求,而不仅仅是表面上看起来。

一个通用的解决方案应该使用-v调用od,以避免重复字符被抑制。 - Martin

0

结合TMS和i-always-rtfm-and-stfw的答案,以下命令可在Windows下使用gnu-utils版本的'od'、'sed'和'tr'程序:

echo "Hello"| tr -d '\42' | tr -d '\n' | tr -d '\r' | od -v -A n -tx1 | sed "s/ //g"

或者在CMD文件中:

@echo "%1"| tr -d '\42' | tr -d '\n' | tr -d '\r' | od -v -A n -tx1 | sed "s/ //g"

我的解决方案的一个限制是它会删除所有双引号(")。
"tr -d '\42'" removes quote marks that the Windows 'echo' will include.
"tr -d '\r'" removes the carriage return, which Windows includes as well as '\n'.
The pipe (|) character must follow immediately after the string or the Windows echo will add that space after the string.
There is no '-n' switch to the Windows echo command.

1
一个通用的解决方案应该使用-v调用od,以避免重复字符被抑制。 - Martin
谢谢您的建议,@Martin。为了测试,我尝试通过大量输出“DDD”(十六进制0x44)来使抑制生效,但没有成功。我猜测在不同的环境中抑制重复字符可能有所不同。尽管如此,这似乎是正确的做法,所以我编辑了我的答案。 - trindflo

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