awk性能和CPU运行时间

时间:2013-02-17 10:59:50

标签: awk cut

我有一个包含数百万行和数千列/字段的输入文件。任何人都可以向我解释,为什么下面两个产生相同输出的awk方法在CPU运行时间方面差别很大?

175.0秒:

awk 'BEGIN{FS=":| "}NR>1{field1=$1;field2=$2;$1="";$2="";print field1":"field2,field1":"field2,field2,$0}' file_in > file_out

19.7秒:

cat file_in | awk 'BEGIN{FS=":"}NR>1{print $1,$2}' | awk '{print $1":"$2,$1":"$2,$0}' | cut -d " " -f 3 --complement > file_out

这是一个file_in的第二行和第三行,只有几百个列/字段(行之间没有换行符):

1:1000071 C T 1 0 0 1 0 0
1:1000759 C T 1 0 0 0 1 0

以下是file_out的相应行:

1:1000071 1:1000071 1000071 C T 1 0 0 1 0 0
1:1000759 1:1000759 1000759 C T 1 0 0 0 1 0

2 个答案:

答案 0 :(得分:6)

这两个陈述:

$1="";$2=""

导致awk重新编译每个记录两次。鉴于每个领域有数百万行和数千个字段,我预计会产生影响。

如果您向我们展示几行代表性样本输入和预期输出,我们可以向您展示如何简洁有效地完成这些操作。

看起来你所做的就是转换这样的行:

1:1000071 C T 1 0 ...
1:1000759 C T 1 0 ...

这样的行:

1:1000071 1:1000071 1000071 C T 1 0 ...
1:1000759 1:1000759 1000759 C T 1 0 ...

如果是这样,您需要做的就是:

awk '{x=$1; sub(/[^:]+:/,x" "x" ")}1' file

或者因为这是一行上的简单替换,即使是sed也可以处理它:

sed 's/\([^:]*:\)\([^ ]*\)/\1\2 \1\2 \2/' file

查找

$ cat file
1:1000071 C T 1 0 ...
1:1000759 C T 1 0 ...

$ awk '{x=$1; sub(/[^:]+:/,x" "x" ")}1' file
1:1000071 1:1000071 1000071 C T 1 0 ...
1:1000759 1:1000759 1000759 C T 1 0 ...

$ sed 's/\([^:]*:\)\([^ ]*\)/\1\2 \1\2 \2/' file
1:1000071 1:1000071 1000071 C T 1 0 ...
1:1000759 1:1000759 1000759 C T 1 0 ...

啊,但我看到你提到你的样本输入来自第2行,所以我猜你有一个标题行或者要跳过的东西。那就是:

awk 'NR>1{x=$1; sub(/[^:]+:/,x" "x" ");print}' file

sed -n '2,$s/\([^:]*:\)\([^ ]*\)/\1\2 \1\2 \2/p' file

最后 - 这是一个替代的awk解决方案,如果您的所有行都以“1:”开头,如示例输入中所示,则可能更有效:

awk 'NR>1{print $1, $1, substr($0,3)}' file

答案 1 :(得分:0)

这仍然是最快的解决方案:

  cat file_in | awk 'BEGIN{FS=":"}NR>1{print $1,$2}' | awk '{print $1":"$2,$1":"$2,$0}' | cut -d " " -f 3 --complement > file_out