2014-08-31 31 views
0

我的CSV文件有一個像檢查正是第N個符號由逗號

start_time,end_time,link 

1407233497,1407233514,http://s.youtube.com/stream_204?event=streamingstats&fmt=n 
1407233498,1407233515,http://s.youtube.com/stream_204?event=cenjreaecnjcd 
mingstats&fmt=n 
1407233499,1407233516,http://s.youtube.com/stream_204?event=weedwcecd 

有些時候鏈接包含新線列,我想刪除它們。我怎樣才能做到這一點從這樣最後輸出的新行變爲:

1407233497,1407233514,http://s.youtube.com/stream_204?event=streamingstats&fmt=n 
1407233498,1407233515,http://s.youtube.com/stream_204?event=cenjreaecnjcdmingstats&fmt=n 
1407233499,1407233516,http://s.youtube.com/stream_204?event=weedwcecd 

我這個AWK一個班輪建議:

awk '{printf "%s%s", (NR>1&&/^[0-9]{10}/?"\n":""),$0}END{print ""}' file 

它的偉大工程,但可能它會檢查第10個符號是否逗號更快?

換行字符可能只是內部鏈接和鏈接不能包含逗號

我會很感激的幫助

+0

我猜測你所擁有的'awk'會比需要計數''的''更快,以獲得新的行。這裏每行只有兩個','。 – Jotne 2014-08-31 10:18:37

+2

所以你有一個awk工作程序,你想要什麼,一個更快的?如果這是一個性能優化問題,則應包括樣本輸入,當前時間和目標時間。 – 2014-08-31 10:20:12

+0

@hash你的意思是在鏈接部分可能有多個換行符? – 2014-08-31 10:20:18

回答

4

當發佈問題以詢問如何解決問題而不是如何針對問題實施特定解決方案時最好,因爲您提出的解決方案或給出的解決方案可能不是您問題的最佳解決方案。

這將解決您的問題更自然的方式,它恰好是比你問的解決方案快:

$ awk -F, '{printf "%s%s",(NR>1&&NF>2?RS:""),$0} END{print ""}' file 
1407233497,1407233514,http://s.youtube.com/stream_204?event=streamingstats&fmt=n 
1407233498,1407233515,http://s.youtube.com/stream_204?event=cenjreaecnjcdmingstats&fmt=n 
1407233499,1407233516,http://s.youtube.com/stream_204?event=weedwcecd 

使用@TomFenechs 242M樣本輸入文件:

$ time awk '{printf "%s%s", (NR>1&&/^[0-9]{10}/?"\n":""),$0}END{print ""}' file > kent.out 

real 0m17.542s 
user 0m16.738s 
sys  0m0.530s 

$ time awk 'BEGIN{FS=OFS=","}NR>1&&NF>2{print a,b}NF>2{a=$1OFS$2;b=$3;next}{b=b$0}END{print a,b}' file > tom.out 

real 0m13.826s 
user 0m13.213s 
sys  0m0.374s 

$ time awk -F, '{printf "%s%s",(NR>1&&NF>2?RS:""),$0} END{print ""}' file > ed.out 

real 0m10.785s 
user 0m10.030s 
sys  0m0.467s 
+1

+1你的速度還是比較快的,所以你贏了:) – 2014-08-31 13:36:44

+0

我真的很驚訝,結果是這樣的結果,因爲字符串連接通常比awk中的I/O更慢,而且你正在爲每個輸入行執行它(' a = $ 10FS $ 2'或'b = b $ 0')。我懷疑它一定是我的printf和你打印的比賽。你可以通過將'NF> 2'的測試移動到一個位置,然後在其動作塊中使用if(NR> 1)打印a,b'來加快你的速度。 – 2014-08-31 13:47:23

+0

@EdMorton BSD'awk'對於最後一個變體仍然需要35秒。 GNU awk v4.1的主頻爲10.4。 – 2014-08-31 13:56:43

1

這裏的另一種方式,你可以做到這一點(我認爲沒有領先文件中的行):

BEGIN { FS = OFS = "," } 
NF>2 { if (NR>1) print a, b; a = $1 OFS $2; b = $3; next } 
{ b = b $0 } 
END { print a, b } 

測試出來:

$ awk -f join.awk file 
1407233497,1407233514,http://s.youtube.com/stream_204?event=streamingstats&fmt=n 
1407233498,1407233515,http://s.youtube.com/stream_204?event=cenjreaecnjcdmingstats&fmt=n 
1407233499,1407233516,http://s.youtube.com/stream_204?event=weedwcecd 

我比較比較,你在一個更大的文件,我的做法的速度:

$ cat file 
1407233497,1407233514,http://s.youtube.com/stream_204?event=streamingstats&fmt=n 
1407233498,1407233515,http://s.youtube.com/stream_204?event=cenjreaecnjcd 
mingstats&fmt=n 
1407233499,1407233516,http://s.youtube.com/stream_204?event=weedwcecd 
$ for i in {1..20}; do cat file file > tmp && mv tmp file; done 
$ du -h file 
242M file 
$ time awk 'BEGIN{FS=OFS=","}NF>2{if(NR>1)print a,b;a=$1OFS$2;b=$3;next}{b=b$0}END{print a,b}' file > /dev/null 

real 0m13.551s 
user 0m13.458s 
sys  0m0.069s 
$ time awk --re-interval '{printf "%s%s", (NR>1&&/^[0-9]{10}/?"\n":""),$0}END{print ""}' file > /dev/null 

real 0m23.438s 
user 0m23.331s 
sys  0m0.066s 

正如你所看到的,我的做法是要快得多。

+1

非常好的答案爲您的10K。測試治具和統計數據不會少! :-)。 – shellter 2014-08-31 12:37:56

+0

我懷疑大幅提升性能的原因在於緩存,因爲我在嘗試時沒有看到任何改進,嘗試在查看時間之前運行每個腳本3次,因爲原始文件只在第一次運行時才緩慢運行執行。不管怎樣,你生產的產品都是不正確的。 – 2014-08-31 12:51:19

+1

@感謝您在我的代碼中發現錯誤。我已經更新了它,現在它產生了正確的輸出。我也更新了時間表。 – 2014-08-31 13:31:16

1

這可能會爲你工作(GNU SED):

sed ':a;$!N;/\n[^,]*$/s/\n//;ta;P;D' file 

讀2號線在時間,如果日第二行不包含逗號,然後將其加入第一行。

+0

不錯,用上面的測試文件花了大約19秒。 – 2014-09-01 00:13:28