为什么在 GNU xargs 中与 `-0` 一起使用时 `-r` 似乎被忽略了?

xen*_*oid 5 gnu xargs

打印换行、xargs调用printf和某些内容的常规情况:

>>printf "foo\n" | xargs -r printf "->%s\n"
->foo
>>
Run Code Online (Sandbox Code Playgroud)

随着空输入代替,-r使得xargs不是在所有调用命令:

>>printf "\n" | xargs -r printf "->%s\n"
>>
Run Code Online (Sandbox Code Playgroud)

使用空值而不是换行符,如果有以下输入,一切都是一样的xargs

>>printf "foo\0" | xargs -r -0 printf "->%s\n"
->foo
>>
Run Code Online (Sandbox Code Playgroud)

但是如果没有输入,无论如何都会打印一些东西:

>>printf "\0" | xargs -r -0 printf "->%s\n"
->
>>
Run Code Online (Sandbox Code Playgroud)

所以,要么

  • 我错过了一些东西(什么?)

  • -r当与-0(但哪个)一起使用时,有一些很好的理由可以忽略?

  • 我的xargs(findutils 4.6.0.225-235f)中有一个错误,但很难决定:

    • 我在另外两个实例(Ubuntu 16.04 上的 4.7.0-git 和 Windows 上的另一个 4.6.0)中发现了相同的行为,
    • 我不敢相信这种事情会通过回归测试。
    • 另一方面,这个问题暗示它在过去可能有效

那么, 的真正预期行为是xargs什么?

Sté*_*las 7

xargs -r cmd跳过cmd没有参数的运行。

使用-0,为每个 NUL 分隔的输入记录创建一个参数

printf '\0' | xargs -r0 cmd
Run Code Online (Sandbox Code Playgroud)

您正在提供一个空记录,因此cmd使用一个空参数调用(并且使用printf '\0\0',这将是 2 个空记录等)。

和:

printf '' | xargs -r0 cmd
Run Code Online (Sandbox Code Playgroud)

你没有记录,所以cmd没有运行。

和:

printf '' | xargs -0 cmd
Run Code Online (Sandbox Code Playgroud)

你仍然没有提供任何记录,但是因为-r没有提供,cmd仍然没有参数地调用一次。

没有-0,xargs需要一个非常特殊的输入格式,它不是一个简单的分隔列表,如 withxargs -0xargs -d '\n'

要提供一个空参数,您需要如下内容:

printf '""\n' | xargs -r cmd
printf "''\n" | xargs -r cmd
Run Code Online (Sandbox Code Playgroud)

或者就此而言:

printf '\n\n \t\t "" \n\n \t\n' | xargs -r cmd
Run Code Online (Sandbox Code Playgroud)

printf -- '-%s\n' 不是测试它的最佳命令选择,因为它在不传递参数时与传递一个空参数时给出相同的输出。

更好的可能是:

$ printf '\n\n \t\t "" \n\n \t\n' | xargs -r zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got: ''
$ printf '\n\n \t\t \n\n \t\n' | xargs zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got:
$ printf '\t\n\n' | xargs -rd '\n' zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got: $'\t' ''
Run Code Online (Sandbox Code Playgroud)

或者:

$ printf '\t\n\0\0' | xargs -0 zsh -c 'print -rl $#: " - ${(q+)^@}"' zsh
2:
 - $'\t\n'
 - ''
Run Code Online (Sandbox Code Playgroud)