简体   繁体   中英

How does this pipeline with printf — “$(cat | sed…)” work?

What is going on in the first snippet with printf -- ? How does printf parse such a command and how does the final call stack look like?

$ 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==

I think you may be misreading the scripts you're asking about.

In the first example, the printf command is simply:

printf '%x' 65537

That will print the number 65537 as a hexadecimal value ( 10001 ). The script then uses the shell pipe symbol ( | ) to pass the output of that printf command into the a second printf command:

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

In this command, the -- simply means "there are no cli options after this", which is used to ensure that anything after -- that looks like an option is not treated like an option. The remainder of the command is a shell $(...) expression, which will be replaced by the output of the commands contained inside the parentheses:

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

It starts with a useless use of cat , which simply passes standard input (...which is the output from the previous printf command...) to stdoutput. The following sed command contains two expressions. The first one...

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

...matches any line containing an odd number of digits and prepends a 0 , ensuring that the every line has an even number of digits. The second expression...

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

Replaces every two characters ( nn ) with \\xnn , which is a printf formatting code that asks printf to print the character with the given ASCII value.

The output from the second printf command is then piped into openssl base64 -e , which produces on stdout the base64 encoding of whatever was received on stdin .


So when you run:

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

This becomes:

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

Which outputs:

AQAB

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM