【发布时间】:2019-07-13 01:52:54
【问题描述】:
在为字符串替换编写 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。当然,这是一个简化的示例,实际用例要复杂得多。
在最初的用例中,我有一个产生大量输出的程序。我通过几个 grep 管道输出以获取感兴趣的行。之后,我将这些行通过管道传输到 sed 以从这些行中提取我需要的数据。因为我需要对数据进行的一些转换太复杂而无法单独使用正则表达式,所以我想为这些使用一个函数。所以,我最初的想法是简单地输入函数,但我无法让它工作并最终得到 xargs 解决方案。我最初的想法是这样的:
command | grep ... | grep ... | grep ... | sed ... | subs
顺便说一句:我不是从命令行执行此操作,而是从脚本中执行此操作。该函数在使用它的同一脚本中定义。
我使用的是 Bash 3.2(Mac OS X 默认),所以花哨的 Bash 4.x 对我没有帮助,抱歉。
我会很高兴所有可能对这个话题有所启发的事情。
最好的问候
弗兰克
【问题讨论】:
-
请记住,xargs 会启动新的子进程,不在现有 shell 中运行(或任何 shell,除非您明确指定将启动子进程的命令)。除非您跳过一些障碍来这样做,否则这些子流程根本不是外壳。
-
...它有助于使用
set -x记录外壳级别发生的事情,这将让您看到 choroba 的答案中描述的行为。 -
(顺便说一句,关于我的建议,您可能真的不需要使用 xargs ——请参阅 BashFAQ #1 以获取有关在不使用本机 bash 的情况下循环面向行的输入的指南)。
-
考虑您是否真的需要命令替换。在这个简单的例子中,
... | xargs -I % subs %可能就足够了。 -
@chepner, ...好吧,如果
subs是一个可以是exec()'d 而不是函数的外部程序就足够了。
标签: linux bash function sed xargs