Bash 用xargs调用shell函数

Bash 用xargs调用shell函数,bash,sh,xargs,Bash,Sh,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或任何其他解决方案来完成此任务的任何想法。导出函数应该可以(未经测试): 您可以使用内置print

我尝试使用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或任何其他解决方案来完成此任务的任何想法。

导出函数应该可以(未经测试):

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

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
另外,使用类似的
返回0
退出0
可以屏蔽它前面的命令可能产生的任何错误值。此外,如果没有错误,则为默认值,因此有些冗余

@恐惧症提到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)
这是使用安全格式输出的内容:

echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'
$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)
这与使用SQL来避免类似


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

使用GNU Parallel is如下所示:

#!/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版本,您甚至不必导出-f,只要您运行了以下操作:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {} 

类似的方法也应该有效:

function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "

也许这是一种不好的做法,但如果您在
.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

似乎我不能发表评论:-(

我想知道我们的重点是什么

bash -c 'echo_var "$@"' _ {}
vs
bash -c 'echo_var "{}"'
第一个将{}替换为bash的arg,而第二个将{}替换为函数的arg

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


更多讨论:xargs执行名为的进程的全新实例。在本例中,您提供了名称
echo\u var
,这是此脚本中的一个函数,而不是进程(程序)在您的路径中。Dennis的解决方案所做的是导出要使用的child bash进程的函数,然后派生到子进程并在那里执行。
\uuu
\
的意义是什么,没有它们它就不起作用了me@Hashbrown:下划线(
\u
)为
argv[0]
$0
)几乎可以在那里使用任何东西。我想我添加了反斜杠分号(
\;
)因为它用于终止
find
中的
-exec
子句,但是在这里没有它的情况下它对我来说是有效的。事实上,如果函数使用
$
而不是
$1
,那么它会将分号视为一个参数,因此应该忽略它。-xargs的i参数已被弃用。使用-i(大写字母i)相反,您可以通过使用
bash-c'echo_var{}'
在bash的命令字符串中包含来自xargs的参数来简化此过程最后。Danger,user1148366,Danger!不要使用bash进行并行编程-你会遇到很多问题。使用C/C++和pthreads,或者Java线程,或者任何让你对所做的事情深思熟虑的东西,因为并行编程需要大量的思考才能正确进行。@DavidSouther如果任务是独立的,比如C将所有这些图片文件转换为png格式,然后别担心。这是在您进行同步时(除了等待所有文件完成)我是一名Java开发人员,最近一直在groovy中工作。我继续告诉人们:朋友们不会让朋友们编写bash脚本。然而,我发现自己看到这篇文章/解决方案是因为(悲伤的脸:()我在bash中从事并行处理。我可以很容易地在groovy/java中完成。糟糕!在osx的何处购买?nvm中也讨论了这一点。它在ZSH中设置,设置如下错误Ole
sh:parallel\u bash\u环境:第67行:在寻找匹配时出现意外EOF
“'sh:parallel\u bash\u环境:第79行:语法错误:意外d文件结尾sh:为
parallel\u bash\u环境'/usr/local/bin/bash:parallel\u bash\u环境导入函数定义时出错:第67行:查找匹配时出现意外EOF
'/usr/local/bin/bash:parallel\u bash\u环境:第79行:语法错误:文件结尾意外/usr/local/bin/bash:error导入函数定义n代表“…你已经被炮击了余震:炮击没有直接影响GNU并行。但是,炮击的解决方案确实:它彻底崩溃了--env和env_并行技巧。据信它在git版本中得到了修复:我喜欢这个答案,因为它让我发现了并行工具