如何在每次匹配的命令替换中使用xargs运行函数?

问题描述 投票:0回答:2

在为字符串替换编写Bash函数时,我在使用xargs时遇到了一种奇怪的行为。这实际上让我很生气,因为我无法让它发挥作用。幸运的是,我已经能够将其归结为以下简单示例:

定义一个简单的函数,它将给定参数的每个字符加倍:

function subs { echo $1 | sed -E "s/(.)/\1\1/g"; }

调用函数:

echo $(subs "ABC")

正如预期的那样,输出是:

AABBCC

现在使用xargs调用该函数:

echo "ABC" | xargs -I % echo $(subs "%")

令人惊讶的是,结果现在是:

ABCABC

似乎函数内部的sed命令现在将整个字符串视为单个字符。为什么会发生这种情况?如何防止这种情况发生?

你可能会问,为什么我会使用xargs。当然,这是一个简化的例子,实际的用例要复杂得多。

在原始用例中,我有一个产生大量输出的程序。我通过几个greps管道输出以获得感兴趣的行。之后,我将线路传输到sed以从线路中提取我需要的数据。因为我需要对数据进行的一些转换太复杂而不能单独使用正则表达式,所以我想为这些使用函数。所以,我最初的想法只是简单地管理功能,但我无法让它工作并最终得到xargs解决方案。我最初的想法是这样的:

command | grep ... | grep ... | grep ... | sed ... | subs

顺便说一句:我不是从命令行执行此操作,而是从脚本中执行此操作。该函数在使用它的完全相同的脚本中定义。

我正在使用Bash 3.2(默认为Mac OS X),所以花哨的Bash 4.x东西对我没用,抱歉。

我会对可能对这一主题有所了解的一切感到高兴。

最好的祝福

坦率

linux bash function sed xargs
2个回答
2
投票

如果你真的需要这样做(你可能没有,但如果没有更具代表性的样本我们就无法帮助),一种更好的练习方法可能如下:

subs() { sed -E "s/(.)/\1\1/g" <<<"$1"; }
export -f subs

echo "ABC" | xargs bash -c 'for arg; do subs "$arg"; done' _
  • 使用echo "$(subs "$arg")"而不仅仅是subs "$arg"只会增加错误(考虑如果你的一个参数是-n会发生什么 - 并且假设相对温和的echo;即使没有-e参数也允许他们使用反斜杠并且做所有方式其他令人惊讶的事情)。你可以在上面做,但它减慢你的程序,使它更容易出现令人惊讶的行为;毫无意义。
  • 运行export -f subs将您的函数导出到环境中,因此它可以由作为子进程调用的其他bash实例运行(xargs调用的所有程序都在shell之外,因此它们无法查看shell局部变量或函数)。
  • 没有-I - 也就是说,在其默认操作模式下 - xargs将参数附加到它给出的命令的末尾。这允许更有效的使用模式,其中不是每行输入调用一个命令,而是将尽可能多的参数传递给尽可能短的子进程。 这也避免了将xargs -Ibash -c '...'sh -c '...'结合使用时可能发生的主要安全漏洞。 (如果您使用过-I% sh -c '...%...',那么您的文件名将成为您的代码的一部分,并且能够用于您系统的注入攻击)。

1
投票

这是因为在解析管道时,构造$(subs "%")被shell扩展,所以xargsecho %%一起运行。

© www.soinside.com 2019 - 2024. All rights reserved.