2014-08-31 69 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