我有一个小的awk脚本,该脚本从流中获取输入,并根据第二列的值写入适当的文件。这是怎么回事:
cat mydir/*.csv | awk -F, '{if(NF==29)print $0 >> "output/"$2".csv"}'
如何并行化它,以便它可以使用机器中可用的多个内核?现在,它正在单个内核上运行。
答案 0 :(得分:0)
未经测试:
do_one() {
# Make a workdir only used by this process to ensure no files are added to in parallel
mkdir -p $1
cd $1
cat ../"$2" | awk -F, '{if(NF==29)print $0 >> $2".csv"}'
}
export -f do_one
parallel do_one workdir-{%} {} ::: mydir/*.csv
ls workdir-*/ | sort -u |
parallel 'cat workdir*/{} > output/{}'
rm -rf workdir-*
如果您想避免多余的cat
,则可以改用它,尽管我发现cat
版本更易于阅读(现代系统http://oletange.blogspot.com/2013/10/useless-use-of-cat.html上的性能通常是相同的):
do_one() {
# Make a workdir only used by this process to ensure no files are added to in parallel
mkdir -p $1
cd $1
awk -F, <../"$2" '{if(NF==29)print $0 >> $2".csv"}'
}
export -f do_one
parallel do_one workdir-{%} {} ::: mydir/*.csv
ls workdir-*/ | sort -u |
parallel 'cat workdir*/{} > output/{}'
rm -rf workdir-*
但是正如@Thor所写,您很可能是I / O饿死了。
答案 1 :(得分:0)
您可以尝试一下。
我每个源文件执行1 awk。将内容放入临时文件中(在每个过程中,它是一系列不同的操作,以避免在同一最终文件中发生冲突和/或在其上打开/关闭句柄过多)。在awk末尾,它将临时文件的内容放入最后一个文件中,并删除了临时文件
如果要处理的文件太多,则可能必须使用批处理限制器(睡眠或更智能的分组),以免杀死并发子进程过多的计算机。
rm output/*.csv
for File in mydir/*.csv
do
# shell sub process
{
# ref for a series of temporary file
FileRef="${File##*/}"
awk -F ',' -v FR="${FileRef}" '
NF == 29 {
# put info in temporary file
ListFiles [ OutTemp = "output/"$2".csv_" FR ] = "output/"$2".csv"
print > OutTemp}
END {
# put temporary content into final file
for ( TempFile in ListFiles ) {
Command = sprintf( "cat \042%s\042 >> \042%s\042; rm \042%s\042" \
, TempFile, ListFiles[TempFile], TempFile )
printf "" | Command
}
' File
} &
done
wait
echo ls -l output/*.csv