bash xargs 中的 printf 转义格式 (%q)

bash printf escaping format (%q) in xargs

考虑下面执行的 bash 命令。

参考man xargs:

-t, --verbose Print the command line on the standard error output before executing it.

# `printf` (1)
echo "meeny miny moe" | xargs -t -I {} printf "%q " "{}"
printf %q  meeny miny moe
'meeny miny moe'

# Then let's try the command output by `xargs`
printf %q  meeny miny moe
meenyminymoe

# `printf` (2)
echo "meeny miny moe" | xargs -t -I {} sh -c 'printf "%q " "$@"' -- "{}"
sh -c printf "%q " "$@" -- meeny miny moe
meeny\ miny\ moe

# Then let's try the command output by `xargs`
sh -c printf "%q " "$@" -- meeny miny moe
printf: usage: printf [-v var] format [arguments]

# `printf` (3)
printf "%q " "meeny miny moe"
meeny\ miny\ moe

好的,(2)等同于(3),对我来说都有意义。我有几个问题。

问题 1 为什么 xargs 使用 -t 输出错误命令:执行此命令会产生与实际 xargs 执行完全不同的结果?那里缺少什么,什么 xargs 没有打印?

问题二 为什么 (1) 的结果与 (2) 和 (3) 的结果不同?是 xargs 对结果输出进行单引号,还是 printf 出于某种原因这样做?

%q替换为%s

echo "meeny miny moe" | xargs -t -I {} printf "%s " "{}"
printf %s  meeny miny moe
meeny miny moe 

结果不同,所以我假设不是xargs在引用输出,是printf吗?如何仅使用 printf 而不使用 xargs 获得相同的结果?为什么 printf 只有 xargs 才会这样?

问题 1

打印命令时,xargs 省略了引号。应该写成:

printf "%q " "meeny miny moe"

没有引号,你得到:

printf %q  meeny miny moe

(注意两个 space 字符)

问题 2

printf %q 1) 和 2) 中的输出不同,但它们都是正确的。

不同之处在于,在 1) 中,您使用的是 printf 可执行文件(可能在 /usr/bin 中,而在 2)中,您使用的是 printf 内置的 shell.

试一试:

$ printf '%q\n' "meeny miny moe"
meeny\ miny\ moe

$ /usr/bin/printf '%q\n' "meeny miny moe"
'meeny miny moe'

$ command printf '%q\n' "meeny miny moe"
meeny\ miny\ moe