是否有可能通过 GNU 并行化 awk 写入多个文件?



我正在运行一个awk脚本,我想通过GNU并行化。

此脚本根据每行上的值将一个输入文件解复用为多个输出文件。代码如下:

#!/usr/bin/awk -f
BEGIN{ FS=OFS="t" }
{
# bc is the field that defines to which file the line
# will be written
bc = $1
# append line to such file
print >> (bc".txt")
}

我想通过以下方式使用 GNU 并行化它:

parallel --line-buffer --block 1G --pipe 'awk script.awk'

但是,我担心两个awk进程同时在同一文件中写入的可能竞争条件。是否可能,如果是,如何在不影响并行化的情况下避免它?

铌。我包含了--line-buffer选项,尽管我不确定它是否也适用于 awk 脚本中的文件重定向。它是否也适用于这种情况,还是仅适用于每个awk进程的标准输出?

# Input file
bc1    line1
bc3    line2
bc1    line3
bc2    line4

# Output file bc1.txt
bc1    line1
bc1    line3
# Output file bc2.txt
bc2    line4
# Output file bc3.txt
bc3    line2

您可以通过解复用不同目录的输出来做到这一点:

stuff |
parallel --block 10M --pipe --round-robin 
'mkdir -p dir-{%}; cd dir-{%}; awk ../script.awk'

或者,如果输入是文件,则可以使用更快的--pipepart

parallel --block -1 --pipepart -a bigfile 
'mkdir -p dir-{%}; cd dir-{%}; awk ../script.awk'

然后没有竞争条件。通过合并目录完成:

parallel 'cd {}; ls' ::: dir-* | sort -u |
parallel 'cat */{} > {}'

如果合并不可接受(也许您没有磁盘空间来存储数据的 2 个副本(,则可以使用 fifos。但是要做到这一点,你需要提前知道所有.txt文件的名称,你需要一个可以并行运行每个名称一个进程的系统(10000 个名称 = 10000 个进程(:

# Generate names-of-files.txt somehow
# Make fifos for all names in all slots
parallel 'mkdir -p {2}; mkfifo {2}/{1}' :::: 
names-of-files.txt <(seq $(parallel --number-of-threads) )
# Run the demultiplexer in the background
parallel --block -1 --pipepart -a bigfile 
'mkdir -p dir-{%}; cd dir-{%}; awk ../script.awk' &
# Start one process per name
# If you have more than 32000 names, you will need to increase the number
# of processes on your system.
cat names-of-files.txt |
parallel -j0 --pipe -N250 -I ,, parallel -j0 'parcat */{} > {}'

相关内容

  • 没有找到相关文章

最新更新