并行化awk脚本-文件拆分

时间:2019-01-03 18:49:43

标签: awk parallel-processing gnu-parallel

我有一个小的awk脚本,该脚本从流中获取输入,并根据第二列的值写入适当的文件。这是怎么回事:

cat mydir/*.csv | awk -F, '{if(NF==29)print $0 >> "output/"$2".csv"}'

如何并行化它,以便它可以使用机器中可用的多个内核?现在,它正在单个内核上运行。

2 个答案:

答案 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