使用printf-“ $(cat | sed ...)”的管道如何工作?

时间:2019-02-26 02:28:51

标签: shell printf

第一个摘录中的printf --发生了什么? printf如何解析这样的命令以及最终调用堆栈如何?

$ printf '%x' 65537 | \
    printf -- \
    "$(cat | sed -E -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')" \
    | openssl base64 -e
AQAB
$ printf '%x' 65537 | \
    cat | sed -E -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g' \
    | openssl base64 -e
XHgwMVx4MDBceDAxCg==

1 个答案:

答案 0 :(得分:2)

我认为您可能会误读您要询问的脚本。

在第一个示例中,printf命令很简单:

printf '%x' 65537

这将打印数字65537作为十六进制值(10001)。然后,脚本使用外壳管道符号(|)将该printf命令的输出传递给第二个printf命令:

printf -- "$(cat | sed -E -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"

在此命令中,--的简单含义是“此后没有cli选项”,用于确保--之后的任何看起来像选项的东西都不被视为选项。该命令的其余部分是一个外壳$(...)表达式,它将由括号内包含的命令输出替换:

cat | sed -E -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')

它以useless use of cat开头,它只是将标准输入(...是前一个printf命令的输出...)传递给stdoutput。以下sed命令包含两个表达式。第一个...

s/^(.(.{2})*)$/0\1/

...匹配包含奇数个数字的任何行,并加上0,以确保每行都有偶数个数字。第二个表达式...

s/(.{2})/\\x\1/g

nn替换每两个字符(\xnn),这是printf的格式代码,要求printf打印具有给定ASCII值的字符。

第二个printf命令的输出然后通过管道传输到openssl base64 -e,后者在stdout上生成stdin上接收到的内容的base64编码。


因此,当您运行时:

printf '%x' 65537 | \
    printf -- \
    "$(cat | sed -E -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')" \
    | openssl base64 -e

它变成:

echo 10001 | printf -- '\x01\x00\x01' | openssl base64 -e

哪个输出:

AQAB