确切地检查第N个符号是逗号

时间:2014-08-31 10:14:53

标签: bash awk sed text-processing

我的CSV文件包含

等列
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个符号是逗号会更快吗?

新行字符只能在链接中使用,链接不能包含逗号

我非常感谢你的帮助

3 个答案:

答案 0 :(得分: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)

这是你可以做到的另一种方式(我假设文件中没有前导线):

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

如您所见,我的方法要快得多。

答案 2 :(得分:1)

这可能适合你(GNU sed):

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

一次读取2行,如果第2行不包含逗号,则将其加入第一行。