2013-02-17 61 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