管道回显输出到 xargs

Posted

技术标签:

【中文标题】管道回显输出到 xargs【英文标题】:Piping echo output into xargs 【发布时间】:2019-01-15 02:58:59 【问题描述】:

我正在尝试通过xargs 传递值列表。这是一个简单的例子:

echo "Hello Hola Bonjour" | xargs -I _ echo _ Landon

我希望这会输出以下内容:

Hello Landon
Hola Landon
Bonjour Landon

相反,命令输出如下:

Hello Hola Bonjour Landon

我错过了什么?

【问题讨论】:

echo "Hello Hola Bonjour" | xargs printf '%s Landon\n' 不会有这个问题(因为printf 在看到额外参数时会重用其格式字符串,printf '%s Landon\n' Hello Hola Bonjour 将打印您期望的三行)。一般来说,最好避免使用xargs -I;当应用于常见用例(例如替换为sh -c '...' 字符串)时,它存在严重的(安全)问题。 【参考方案1】:

-I 下,man xargs

未加引号的空格不会终止输入项;取而代之的是 分隔符是换行符

您可以指定不同的分隔符(至少在 GNU xargs 中):

printf 'Hello Hola Bonjour' | xargs -d' ' -I _ echo _ Landon

更便携,使用\0作为分隔符,使用-0

printf '%s\0' Hello Hola Bonjour | xargs -0 -I _ echo _ Landon

【讨论】:

对 macOS 有什么建议吗? -d 标志不可用。 @LandonSchropp ...一般来说,最佳实践是使用 NUL 分隔符,而不是空格换行符:printf '%s\0' Hello Hola Bonjour | xargs -0 -I _ echo _ Landon。 NUL 是唯一不能存在于 C 字符串(文件名等)中的字符,因此它是唯一可以保证安全用于分隔任意字符串的字符; xargs -0 在 MacOS 上可用。 @LandonSchropp Mac 的 BSD 工具在很大程度上是不可移植的。你可以安装更便携的 GNU 版本,brew install findutils。 This answer 有一些额外的细节。【参考方案2】:

分隔符需要更改,您还必须指定 -L 选项。因此,要么像建议的其他答案一样通过 -d 更改分隔符,要么通过管道 sed 并用换行符替换空格

echo "Hello Hola Bonjour" | sed -e 's/ /\n/g' | xargs -L 1 -I _ echo _ Landon

结果

Hello Landon
Hola Landon
Bonjour Landon

有时更改分隔符是不够的。 xargs 有时会获取所有输入参数并一次传递所有参数。没有拆分参数。

例如

seq 1 7 | xargs echo

结果

1
2
3
4
5
6
7

被传递给 xargs,所以输出将是

  1 2 3 4 5 6 7

如果添加 xargs 手册页中显示的 -L 1

-L 最大线数 每个命令行最多使用 max-lines 非空白输入行。尾随空格导致输入行 逻辑上继续下一个输入行。隐含 -x。

seq 1 7 | xargs -L 1 echo

然后你会看到

1
2
3
4
5
6
7

您还可以手动将其转换为 for 循环,这样您就可以更轻松地设置多行语句。

# be absolutely sure the values the for loop iterates over is well sanitized to avoid glob expansion of the *.
for i in Hello Hola Bonjour
do
  if [ "$i" = "Hello" ]
  then
    echo "$i Landon, language detected as English!"
  else
    echo "$i Landon, language detected as non English."
  fi
done

【讨论】:

【参考方案3】:

-I 标志将分隔符更改为换行符。

未加引号的空格不会终止输入项;而是分隔符是换行符。

你可以阅读它here。

您必须手动将分隔符指定为空格。默认情况下,Echo 还会插入一个换行符,这会弄乱 xargs。使用 -n 标志删除换行符。

这里是固定的命令:

echo -n "Hello Hola Bonjour" | xargs -d' ' -I _ echo _ Landon

【讨论】:

以上是关于管道回显输出到 xargs的主要内容,如果未能解决你的问题,请参考以下文章

回显shell转义参数[重复]

匿名管道读取CMD回显信息

当流管道用于缓冲时,节点回显服务器降级 10 倍

使用 VBScript 将代码回显到文件中

最简单的nodejs回显服务器

SLURM - 回显输出文件以便在屏幕上打印?