我正在尝试使用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来完成这个任务的想法,或者其他解决方案,都欢迎提供。我正在尝试使用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来完成这个任务的想法,或者其他解决方案,都欢迎提供。导出该函数应该可以解决问题(未经测试):
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 0
和exit 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)
我在这里使用date
命令替代Sasha评论中使用的rm
命令,因为它是非破坏性的,可以用于命令替换或转义引号。
_
)提供了一个占位符,用于代替argv[0]
($0
),几乎可以使用任何内容。我认为我添加反斜杠分号(\;
)是因为它在终止find
的-exec
子句中使用,但是在这里没有也可以正常工作。实际上,如果该函数使用$@
而不是$1
,那么它会将分号视为参数,因此应将其省略。 - Dennis Williamsonbash -c 'echo_var "{}"'
。因此您不需要在末尾使用_ {}
。 - phobic使用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 {}
sh:parallel_bash_environment:第67行:查找匹配''时意外的EOF sh:parallel_bash_environment:第79行:语法错误:意外的文件结尾 sh:导入函数定义时出错,用于“parallel_bash_environment” /usr/local/bin/bash:parallel_bash_environment:第67行:查找匹配''时意外的EOF /usr/local/bin/bash:parallel_bash_environment:第79行:语法错误:意外的文件结尾 /usr/local/bin/bash:导入函数定义时出错,用于
... - Nick这样做也应该可以:
function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
|
,#
)上中断,并忽略输入中的空格。我建议不要让bash将输入视为代码,而是建议让xargs按原样传递它们。 echo {1..10} | xargs -n 1 -P4 bash -c "$(declare -f testing);"' testing "$@"; echo "$@";' argv0
- EndlosSchleife看起来我无法发表评论:-(
我在思考关注重点的问题
bash -c 'echo_var "$@"' _ {}
vs
bash -c 'echo_var "{}"'
$ 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)
也许这是不太好的做法,但如果你在.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
xargs
,可以处理函数。function my_echo() {
echo "$@"
}
echo 1 2 3 | xargs my_echo
# xargs: my_echo: No such file or directory
echo 1 2 3 | xargs2 my_echo
# 1 2 3
xargs2
本身:
is_function() {
if [[ $(type -t "${1?ensure_is_a_function: provide a command}") == "function" ]]; then
return 0
else
return 1
fi
}
function xargs2 {
if is_function "$1"; then
export -f "${1?}" # so subprocess bash can see it
else
echo "xargs2: use xargs" >&2
return 1
fi
ARGS=$(printf "%q " "$@") # escape
cat </dev/stdin | xargs bash -c "$ARGS \$@" _
}