Shell 使用xargs-P时如何将代码提取到函数中?
首先,我已经编写了代码,并且运行良好Shell 使用xargs-P时如何将代码提取到函数中?,shell,sh,xargs,Shell,Sh,Xargs,首先,我已经编写了代码,并且运行良好 # version1 all_num=10 thread_num=5 a=$(date +%H%M%S) seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c 'echo abc{}' b=$(date +%H%M%S) echo -e "startTime:\t$a" echo -e "endTime:\t$b" 现在我想将代码提取到一个函数中
# version1
all_num=10
thread_num=5
a=$(date +%H%M%S)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c 'echo abc{}'
b=$(date +%H%M%S)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
现在我想将代码提取到一个函数中,但它是错误的,如何修复它
get_file(i){
echo "abc"+i
}
all_num=10
thread_num=5
a=$(date +%H%M%S)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c "$(get_file {})"
b=$(date +%H%M%S)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
由于
/bin/sh
不能保证支持打印定义函数的文本,也不能通过环境导出函数,因此我们需要以艰难的方式完成这项工作,只需在xargs启动的sh
副本中复制函数的文本即可
本站点中已经存在其他问题,描述了如何使用bash实现这一点,这相当容易。见f/e
注:
不能保证与echo-e
一起使用。此外,为了使shell真正兼容,需要将/bin/sh
写入其输出。请参见的和的应用程序使用部分-e
- 把
放在{}
的位置是一个非常糟糕的主意。考虑在一个文件名中传递的情况,该文件名包含“代码> $(RM -Rf~)”$(RM- Rf~)'/COD>——它不能被安全地插入到未引用的上下文中,或双引号上下文,或单个引用的上下文,或遗传。< /LI>sh-c'.{}…'
- 请注意,
也是非标准的,不保证在所有符合POSIX的系统上都存在<代码>i=0;而[“$i”-lt“$all_num”];做回显“$i”;i=$((i+1));完成是一种可用于所有POSIX系统的替代方案seq
-I{}
和sh-c'{}…'
组合使用--在这条道路上存在shell注入漏洞。让xargs将内容添加到shell的参数列表中,默认情况下不使用-I
,并编写脚本来迭代这些参数。顺便问一下,您真的需要/bin/sh
?使用bash会容易得多。@KamilCuk,不,argdo的实际上是兼容POSIX的。我自己也弄错了,几年前这里有人用规范的链接纠正了我。哦,真的吗?啊,我的天。那么,我有一些规格阅读要做!谢谢$(date+%H%M%S)#警告:这真的很低效,有什么有效的方法@CharlesDuffy@flower,嗯,对于/bin/sh
没有有效的方法,但是对于bash,printf-va%%(%H%M%S)T'-1
是内置的等价于a=$(date+%H%M%S)
@KamilCuk,我不得不去查阅它以刷新我的记忆——在语法中,请参见第一个选项,for_子句:for name do_group
——尽管从当前规范版本来看,for name sequential_sep do_group
同样有效,因此符合2018版本(至少)的shell必须接受for arg;即使在
中没有,也要执行
。
#!/bin/sh
all_num=10
thread_num=5
batch_size=1 # but with a larger all_num, turn this up to start fewer copies of sh
a=$(date +%H%M%S) # warning: this is really inefficient
seq 1 ${all_num} | xargs -n "${batch_size}" -P "${thread_num}" sh -c '
get_file() { i=$1; echo "abc ${i}"; }
for arg do
get_file "$arg"
done
' _
b=$(date +%H%M%S)
printf 'startTime:\t%s\n' "$a"
printf 'endTime:\t%s\n' "$b"