2013-02-17 37 views
1

我有一个包含数百万行和数千个列/字段的输入文件。任何人都可以向我解释,为什么下面两种awk方法产生相同的输出,在CPU运行时间方面差异如此之大?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只需几百列/场中的第3行(有线之间没有断线):

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 
+0

1st比2nd慢吗?哦...我以为2nd会慢一点.... – Kent 2013-02-17 11:06:55

+1

@Kent字符串连接在awk中很慢,因为它需要计算结果字符串的大小,找到一个足够容纳该字符串的内存区域,将字符串放在那里,然后释放原始的内存区域。它比I/O更慢,所以“打印一个;打印b'而不是'c = a“\ n”b;打印c'。所以通过给字段赋值来重新赋值$ 0可能是这里的罪魁祸首。 – 2013-02-17 11:16:20

回答

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 
6

这2个语句:

$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 
+0

我将输入的第2行和第3行以及输出的第1行和第2行添加到了我的答案中。 – 2013-02-17 22:11:46

+0

@ tommy.carstensen不能添加REPRESENTATIVE输入,只有5或6个字段而不是100个字符的行,所以我们可以更容易地看到将输入转换为输出的过程。 – 2013-02-17 22:16:03