221

我正在尝试使用 xargs 并行调用更复杂的函数。

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var {} 
exit 0

这将返回错误

xargs: echo_var: No such file or directory

任何关于如何使用 xargs 来完成此任务的想法或任何其他解决方案都将受到欢迎。

4

5 回答 5

214

导出函数应该这样做(未经测试):

export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

您可以使用内置printf而不是外部seq

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

此外,使用return 0exit 0类似的方式会掩盖其前面的命令可能产生的任何错误值。此外,如果没有错误,这是默认设置,因此有些多余。

@phobic 提到 Bash 命令可以简化为

bash -c 'echo_var "{}"'

{}直接在里面移动。正如@Sasha 所指出的,它很容易受到命令注入的影响。

下面是一个为什么你不应该使用嵌入格式的例子:

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "{}"'
Sun Aug 18 11:56:45 CDT 2019

为什么不的另一个例子:

echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'

这是使用安全格式输出的内容:

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)

这相当于使用参数化SQL查询来避免注入

我在date这里使用命令替换或转义引号,而不是rmSasha 评论中使用的命令,因为它是非破坏性的。

于 2012-06-12T19:26:02.587 回答
18

使用 GNU Parallel 看起来像这样:

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
export -f echo_var
seq -f "n%04g" 1 100 | parallel -P 10 echo_var {} 
exit 0

如果您使用版本 20170822,您甚至不必export -f运行此命令:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {} 
于 2014-09-01T06:47:45.967 回答
14

像这样的东西也应该起作用:

function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
于 2016-06-22T11:56:25.947 回答
2

也许这是不好的做法,但是如果您在.bashrc脚本或其他脚本中定义函数,则可以使用以下设置包装文件或至少函数定义allexport

set -o allexport

function funcy_town {
  echo 'this is a function'
}
function func_rock {
  echo 'this is a function, but different'
}
function cyber_func {
  echo 'this function does important things'
}
function the_man_from_funcle {
  echo 'not gonna lie'
}
function funcle_wiggly {
  echo 'at this point I\'m doing it for the funny names'
}
function extreme_function {
  echo 'goodbye'
}

set +o allexport
于 2017-12-02T01:01:11.627 回答
2

看来我不能发表评论:-(

我想知道重点

bash -c 'echo_var "$@"' _ {}
vs
bash -c 'echo_var "{}"'

第一个将 {} 替换为 bash 的 arg,而第二个替换为函数的 arg。示例 1 没有扩展 $(date) 的事实只是一个副作用。

如果您不希望函数 args 展开,请使用单引号而不是双引号。为避免嵌套混乱,请使用双引号(在另一个上展开 args)

$ echo '$(date)' | xargs -0 -L1 -I {} bash -c 'printit "{}"'
Fri 11 Sep 17:02:24 BST 2020

$ echo '$(date)' | xargs -0 -L1 -I {} bash -c "printit '{}'"
$(date)
于 2020-09-11T16:26:31.287 回答