awk 从一个文件中读取并拆分标头,在其他文件上使用它

awk 从一个文件中读取并拆分标头,在其他文件上使用它

我正在使用 awk 脚本,该脚本获取第 166 列之后的列标题并将其打印到后续的每一行中。

前任。

col165    col166    col167
a         1         2
b         3         4
c         5         6

变成——

col165    col166    col167
a         col166|1         col167|2
b         col166|3         col167|4
c         col166|5         col167|6

然而,我正在处理的文件相当大(大约 160 万行),大约需要 1.5 小时来处理。

为了加快处理速度,我想到将大文件拆分为 100k 行,然后使用 gnuparallel单独处理每个文件。但是,我遇到了一个问题,该脚本获取文件的标头并使用它来获取标头。我想使用另一个文件来指定标头,否则我必须向每个拆分文件添加标头(这本身看起来很麻烦)。

我正在使用的代码是 -

awk 'BEGIN { FS="\t";OFS="\t" };
     NR == 1 { split($0, headers); print; next }
     {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' input > output

我想使用一个文件column_headers来指定标题。可能吗?

我尝试了以下代码,但它不起作用,我不确定我的代码是否正确:

awk -v head='$(cat column_headers)' 'BEGIN{ FS="\t";OFS="\t" };
        NR == 1 { split($head, headers); print; next }
        {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' input > output

我觉得我做错了什么,但不确定是什么。如能得到任何帮助,我将不胜感激。

编辑:谢谢。我错过了链中的另一个命令,这实际上是长期以来的罪魁祸首。

正如 @Ole Tange 提到的,我使用了该命令,但稍微修改了它 -

time cat input_1|parallel -k -q -j 24 --tmpdir tmp/ --block 900M --pipe awk -f culprit_script > output

该脚本基本上分割每个字段,并根据它们的值删除/保留它们。

第一个命令的执行时间约为 15-20 分钟,第二个脚本只需要一个多小时。使用并行和 24 个线程,7 分钟内完成!我想我也会对第一个命令使用并行:P

感谢大家的意见和建议!

答案1

不是真正的答案,但太大并且需要格式化,所以它不能成为评论,所以......

1.6M 并不是一个巨大的行数。正如你所说,你看到的每小时 100 万行是大规模地慢,每分钟 100 万行会更合理。例如,我通过运行以下脚本创建了一个 1,600,000 行长的文件,每行有 300 列:

$ awk -v n=1600000 -v c=300 -v OFS='\t' 'BEGIN{for (j=1;j<=c;j++) printf "col%s%s",j,(j<c?OFS:ORS); for (i=1;i<=n;i++) for (j=1;j<=c;j++) printf "%s%s",j,(j<c?OFS:ORS)}' > file

然后我定时运行一个脚本来对该文件的问题中进行转换:

$ time awk 'BEGIN{FS=OFS="\t"} NR==1{split($0, headers); print; next} {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' file > out

real    1m22.569s
user    1m17.971s
sys     0m4.359s

因此,运行时间约为 82 秒,而不是 1.5 小时。

答案2

对于 GNU Parallel,它看起来有点像这样:

#!/bin/bash

do_block() {
    awk 'BEGIN{FS=OFS="\t"}
     NR==1{split($0, headers); next}
     {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1'
}
export -f do_block

# Non-parallel version
cat file | head -n1 > out1
time cat file | do_block >> out1

# Parallel version
cat file | head -n1 > out2
time parallel -k --pipepart --block -30 -a file --header : do_block >> out2

在我的 4 核 CPU 上,并行版本的速度大约快 3 倍。

相关内容