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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6791798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 05:13:24  来源:igfitidea点击:

Convert string to hexadecimal on command line

linuxstringcommand-linehexprintf

提问by Eamorr

I'm trying to convert "Hello" to 48 65 6c 6c 6fin hexadecimal as efficiently as possible using the command line.

我正在尝试48 65 6c 6c 6f使用命令行尽可能有效地将“Hello”转换为十六进制。

I've tried looking at printfand google, but I can't get anywhere.

我试过查看printf和谷歌,但我无处可去。

Any help greatly appreciated.

非常感谢任何帮助。

Many thanks in advance,

提前谢谢了,

采纳答案by TMS

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

Explanation:

解释:

  • The echoprogram will provide the string to the next command.
  • The -nflag tells echo to not generate a new line at the end of the "Hello".
  • The odprogram is the "octal dump" program. (We will be providing a flag to tell it to dump it in hexadecimal instead of octal.)
  • The -A nflag is short for --address-radix=n, with n being short for "none". Without this part, the command would output an ugly numerical address prefix on the left side. This is useful for large dumps, but for a short string it is unnecessary.
  • The -t x1flag is short for --format=x1, with the x being short for "hexidecimal" and the 1 meaning 1 byte.
  • echo计划将提供该字符串的下一个命令。
  • -n标志告诉 echo 不要在“Hello”的末尾生成新行。
  • od程序是“八进制转储”程序。(我们将提供一个标志,告诉它以十六进制而不是八进制转储它。)
  • -A n标志是 的缩写--address-radix=n,n 是“无”的缩写。如果没有这部分,该命令将在左侧输出一个丑陋的数字地址前缀。这对于大型转储很有用,但对于短字符串则没有必要。
  • -t x1标志是 的缩写--format=x1,x 是“十六进制”的缩写,1 表示 1 个字节。

回答by I_always_RTFM_and_STFW

If you want to do this and remove the spaces you need:

如果你想这样做并删除你需要的空格:

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

The first two commands in the pipeline are well explained by @TMS in his answer, as edited by @James. The last command differs from @TMS comment in that it is both correct and has been tested. The explanation is:

@TMS 在他的回答中很好地解释了管道中的前两个命令,由@James 编辑。最后一条命令与@TMS 注释的不同之处在于它既正确又经过测试。解释是:

  • sedis a stream editor.
  • sis the substitute command.
  • /opens a regular expression - any character may be used. /is conventional, but inconvenient for processing, say, XML or path names.
  • /or the alternate character you chose, closes the regular expression and opens the substitution string.
  • In / */the *matches any sequence of the previous character (in this case, a space).
  • /or the alternate character you chose, closes the substitution string. In this case, the substitution string //is empty, i.e. the match is deleted.
  • gis the option to do this substitution globally on each line instead of just once for each line.
  • The quotes keep the command parser from getting confused - the whole sequence is passed to sedas the first option, namely, a sedscript.
  • sed是一个小号treamitor。
  • s小号ubstitute命令。
  • /打开一个正则表达式 - 可以使用任何字符。 /是传统的,但不方便处理,例如 XML 或路径名。
  • /或您选择的替代字符,关闭正则表达式并打开替换字符串。
  • / */*匹配前一字符的任何序列(在此情况下,空间)。
  • /或您选择的替代字符,关闭替换字符串。在这种情况下,替换字符串//为空,即删除匹配项。
  • g是做这个替代选项每行,而不是为每一行lobally只有一次。
  • 引号可防止命令解析器混淆 - 整个序列sed作为第一个选项传递给,即sed脚本。

@TMS brain child (sed 's/^ *//') only strips spaces from the beginning of each line (^matches the beginning of the line - 'pattern space' in sed-speak).

@TMS 脑子 ( sed 's/^ *//') 只从每行的开头去除空格(^匹配行的开头 -sed说话中的“模式空间” )。

If you additionally want to remove newlines, the easiest way is to append

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

| tr -d '\n'

to the command pipes. It functions as follows:

到命令管道。它的作用如下:

  • |feeds the previously processed stream to this command's standard input.
  • tris the translate command.
  • -dspecifies deleting the match characters.
  • Quotes list your match characters - in this case just newline (\n). Translate only matches single characters, not sequences.
  • |将先前处理的流提供给此命令的标准输入。
  • trTRanslate命令。
  • -d指定删除匹配字符。
  • 引号列出您的匹配字符 - 在这种情况下只是换行符 ( \n)。翻译只匹配单个字符,不匹配序列。

sedis uniquely retarded when dealing with newlines. This is because sedis one of the oldest unixcommands - it was created before people really knew what they were doing. Pervasive legacy software keeps it from being fixed. I know this because I was born before unixwas born.

sed在处理换行符时是独一无二的。这是因为它是sed最古老的unix命令之一——它是在人们真正知道他们在做什么之前创建的。普遍存在的遗留软件使其无法修复。我知道这一点,因为我在出生之前unix就出生了。

The historical origin of the problem was the idea that a newline was a line separator, not part of the line. It was therefore stripped by line processing utilities and reinserted by output utilities. The trouble is, this makes assumptions about the structure of user data and imposes unnatural restrictions in many settings. sed's inability to easily remove newlines is one of the most common examples of that malformed ideology causing grief.

问题的历史起源是换行符是行分隔符,而不是行的一部分。因此,它被线路处理实用程序剥离并由输出实用程序重新插入。问题是,这对用户数据的结构做出了假设,并在许多设置中施加了不自然的限制。 sed无法轻松删除换行符是导致悲伤的畸形意识形态的最常见例子之一。

It is possible to remove newlines with sed- it is just that all solutions I know about make sedprocess the whole file at once, which chokes for very large files, defeating the purpose of a stream editor. Any solution that retains line processing, if it is possible, would be an unreadable rat's nest of multiple pipes.

可以删除换行符sed- 只是我所知道的所有解决方案都会同时sed处理整个文件,这对于非常大的文件来说会令人窒息,从而违背了流编辑器的目的。如果可能的话,任何保留线路处理的解决方案都将是一个无法阅读的多个管道的老鼠窝。

If you insist on using sedtry:

如果你坚持使用sedtry:

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

-ztells sedto use nulls as line separators.

-z告诉sed使用空值作为行分隔符。

Internally, a string in Cis terminated with a null. The -zoption is also a result of legacy, provided as a convenience for Cprogrammers who might like to use a temporary file filled with C-strings and uncluttered by newlines. They can then easily read and process one string at a time. Again, the early assumptions about use cases impose artificial restrictions on user data.

在内部,字符串 inC以 null 结尾。该-z选项也是遗留的结果,为C可能喜欢使用填充了C-strings 且没有换行符的临时文件的程序员提供了便利。然后,他们可以轻松地一次读取和处理一个字符串。同样,关于用例的早期假设对用户数据施加了人为的限制。

If you omit the goption, this command removes only the first newline. With the -zoption sedinterprets the entire file as one line (unless there are stray nulls embedded in the file), terminated by a null and so this also chokes on large files.

如果省略该g选项,则此命令仅删除第一个换行符。使用该-z选项sed将整个文件解释为一行(除非文件中嵌入了杂散空值),以空值终止,因此这也会阻塞大文件。

You might think

你可能认为

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

might work. The first command puts a null at the front of each line on a line by line basis, resulting in \n\x00ending every line. The second command removes one newline from each line, now delimited by nulls - there will be only one newline by virtue of the first command. All that is left are the spurious nulls. So far so good. The broken idea here is that the pipe will feed the last command on a line by line basis, since that is how the stream was built. Actually, the last command, as written, will only remove one null since now the entire file has no newlines and is therefore one line.

可能工作。第一个命令逐行在每行的前面放置一个空值,从而\n\x00结束每一行。第二个命令从每行中删除一个换行符,现在由空值分隔 - 由于第一个命令,将只有一个换行符。剩下的就是虚假的空值。到现在为止还挺好。这里的坏主意是管道将逐行提供最后一个命令,因为这就是流的构建方式。实际上,正如所写的,最后一个命令只会删除一个空值,因为现在整个文件没有换行符,因此只有一行。

Simple pipe implementation uses an intermediate temporary file and all input is processed and fed to the file. The next command may be running in another thread, concurrently reading that file, but it just sees the stream as a whole (albeit incomplete) and has no awareness of the chunk boundaries feeding the file. Even if the pipe is a memory buffer, the next command sees the stream as a whole. The defect is inextricably baked into sed.

简单的管道实现使用一个中间临时文件,所有输入都被处理并馈送到文件中。下一个命令可能正在另一个线程中运行,同时读取该文件,但它只是将流视为一个整体(尽管不完整)并且不知道提供文件的块边界。即使管道是内存缓冲区,下一个命令也会将流视为一个整体。缺陷难解难分sed

To make this approach work, you need a goption on the last command, so again, it chokes on large files.

要使这种方法起作用,您需要g在最后一个命令上添加一个选项,因此它会再次阻塞大文件。

The bottom line is this: don't use sedto process newlines.

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

回答by Tony Su

Playing around with this further, A working solution is to remove the "*", it is unnecessary for both the original requirement to simply remove spaces as well if substituting an actual character is desired, as follows

进一步解决这个问题,一个可行的解决方案是删除“*”,如果需要替换实际字符,则原始要求也不需要简单地删除空格,如下所示

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

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

So, I consider this as an improvement answering the original Q since the statement now does exactly what is required, not just apparently.

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

回答by trindflo

Combining the answers from TMS and i-always-rtfm-and-stfw, the following works under Windows using gnu-utils versions of the programs 'od', 'sed', and 'tr':

结合 TMS 和 i-always-rtfm-and-stfw 的答案,以下在 Windows 下使用 gnu-utils 版本的程序“od”、“sed”和“tr”运行:

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

or in a CMD file as:

或在 CMD 文件中:

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

A limitation on my solution is it will remove all double quotes (").

我的解决方案的一个限制是它会删除所有双引号 (")。

"tr -d ''" 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.