在一次调用中使用行作为参数(类似 xargs)

在一次调用中使用行作为参数(类似 xargs)

我有一个函数可以打印几行,我想将它们用作另一个函数的参数:

lsx() {
    echo 1 is one
    echo 2 are two
}

somefun() {
    for arg in "$@"; do
        echo "arg='$arg'"
    done
}

我怎样才能“优雅地”somefun()使用来自的行lsx()作为参数进行调用?

我现在所做的是使用循环遍历行while,将行存储在数组中,但这看起来很丑陋而且太有效了。(编辑:由于 while+subshel​​l,这不起作用)。我认为应该有一种简单的(甚至是便携式的?)方法,但无法想出一种方法。

(如果somefun是外部命令那么我就使用参数但事实并非如此。)

答案1

没有 xargs

$ ( IFS=$'\n'; somefun $(lsx) )
arg='1 is one'
arg='2 are two'

使用子 shell 是为了使更改IFS是本地的,而不是全局的。

局限性:这会使 的输出受到lsx路径名扩展的影响,这可能是也可能不是问题。

与 xargs

要使用 xargs 访问 shell 函数,我们需要运行 shell。要访问somefun子 shell,我们首先需要导出它。因此:

$ export -f somefun
$ lsx | xargs -d'\n' bash -c 'somefun "$@"' SomeFun
arg='1 is one'
arg='2 are two'

第一个参数bash被分配给$0并用作错误消息中的程序名称。这可以是任意单词。在这里,我们使用SomeFun.

路径名扩展问题的示例

$ lsx() { echo '1 is one*'; echo '2 are two*'; }
$ touch '1 is one'{1..3} two{a..c}
$ ( IFS=$'\n'; somefun $(lsx) )
arg='1 is one1'
arg='1 is one2'
arg='1 is one3'
arg='2 are two*'

正如您所看到的,输出的第一行被扩展为三行。

shell 首先执行分词在 的输出上$(lsx)。由于 IFS 设置为换行符,因此输出被分成几行。然后 shell 执行路径名扩展。由于存在与 glob 匹配的文件1 is one*,因此该 glob 会扩展为这些名称的列表。在我们的示例中,没有与 glob 匹配的文件2 is two*,因此该 glob 不会扩展。 (在默认的 IFS 下,2 is two*将被分成三个单词,第三个单词将匹配文件twoatwobtwoc。)

xargs方法避免了路径名扩展:

$ export -f somefun
$ lsx | xargs -d'\n' bash -c 'somefun "$@"' SomeFun
arg='1 is one*'
arg='2 are two*'

答案2

简单的解决方案:

IFS="
"
somefun $(lsx)

相关内容