2010-03-29 22 views
36

我有一个制表符分隔的文件,它拥有超过2亿行。在linux中将其转换为csv文件的最快方式是什么?这个文件确实有多行标题信息,我需要将它们排除在外,但标题的行数是已知的。我看到sedgawk的建议,但我想知道是否有“首选”选项。最快的方式将制表符分隔的文件转换为linux中的csv

只是为了澄清,此文件中没有嵌入式选项卡。

+0

对于CSV以TSV和嵌入式分隔符的问题,又见回答到http://stackoverflow.com/questions/13475535/replace-every-comma-not-enclosed-in-a-pair-of-double - (与相关的:http://unix.stackexchange.com/questions/48672/remove-comma-between-the-quotes-only-in-a-comma-delimited-file)。 – 2015-12-26 21:18:56

回答

38

如果您只需要做的是翻译所有制表符到逗号字符,tr可能是要走的路。

这里的空格是文字标签:

$ echo "hello world" | tr "\\t" "," 
hello,world 

当然,如果你已经在文件中嵌入字符串文字内的标签,这会不正确地翻译那些为好;但嵌入的文字标签将是相当不常见的。

+13

更常见的是在源代码中嵌入逗号,然后需要用引号包装。如果有嵌入式引用,这很麻烦... – kibibu 2010-03-29 01:09:15

+0

感谢您提供'tr'建议。它如何与速度相比'sed'?假设您想要跳过行号为x的头文件并继续执行文件的其余部分。有没有一种方法可以用'tr'来实现呢? (我也应该澄清,文件中没有嵌入逗号。) – andrewj 2010-03-29 01:10:04

+0

@andrewj:'tr'应该快得多,因为它只是逐字替换而不是正则表达式匹配。至于跳过标题,最简单的事情就是只处理两个区块 - 如果你知道长度,可以输入“head -n ”输出; tail -n + 输入| tr ... >> output';如果你不知道长度,可能与'grep -n'有关...... – Cascabel 2010-03-29 01:13:37

62

如果您担心嵌入逗号,那么您需要使用稍微更智能的方法。下面是一个Python脚本,从标准输入采用TSV线和写入CSV行到stdout:

import sys 
import csv 

tabin = csv.reader(sys.stdin, dialect=csv.excel_tab) 
commaout = csv.writer(sys.stdout, dialect=csv.excel) 
for row in tabin: 
    commaout.writerow(row) 

运行它从一个shell如下:

python script.py <input.tsv> output.csv 
+1

除非您确定没有嵌入的逗号并且没有嵌入的选项卡,否则这是一种非常可靠的方法。尽管它可能不符合“最快”的标准。 – leedm777 2010-03-29 03:00:49

+2

它可能不是“最快”的,但它确实为我处理嵌入式制表符和逗号。 – anshuman 2014-04-08 19:27:31

+1

这个岩石。我正在编写一个神秘的sed脚本来在bash中处理这个问题 - 但这无法与python csv库的完整性相竞争。谢谢伊格纳西奥,为这次发售。关于速度 - 易用性和可靠性方式的出门速度 - 这当然是足够快的。 :-) – dlink 2014-10-28 14:35:08

3

假设你不想改变头和假设您没有嵌入式选项卡

# cat file 
header header header 
one  two  three 

$ awk 'NR>1{$1=$1}1' OFS="," file 
header header header 
one,two,three 

NR> 1跳过第一个标头。你提到你知道有多少行标题,所以使用正确的数字作为你自己的情况。有了这个,你也不需要调用任何其他的外部命令。只有一个awk命令可以完成这项工作。

另一种方式,如果你有空白列,你在乎。

awk 'NR>1{gsub("\t",",")}1' file 

使用sed的

sed '2,$y/\t/,/' file #skip 1 line header and translate (same as tr) 
6
sed -e 's/"/\\"/g' -e 's/<tab>/","/g' -e 's/^/"/' -e 's/$/"/' infile > outfile 

该死的批评家,报价一切,CSV并不关心。

<tab>是实际的制表符。 \ t不适合我。在bash中,使用^ V输入它。

+0

For你可以做'sed -e's /“/ \\”/ g'-e“s/\ t/\”,\“/ g”-e's/^ /“/'-e's/$ /“/'infile> outfile'。 – 2016-01-12 19:24:43

15
perl -lpe 's/"/""/g; s/^|$/"/g; s/\t/","/g' <input.tab> output.csv 

Perl比sed,awk和Python更快。

+1

对我来说最好的答案是,只有一个稍微改变,scape双引号:perl -lpe's /”/ \\“/ g; s/^ | $ /”/ g; s/\ t /“,”/ g'<... – Lix 2014-12-10 23:55:18

+0

万岁的Perl!确切地说,我需要的是一行代码。 – Debriter 2016-07-26 22:08:00

+0

你是个救世主 – Yankee 2018-02-27 09:54:57

0

以下AWK oneliner支持引述+报价转义

printf "flop\tflap\"" | awk -F '\t' '{ gsub(/"/,"\"\"\"",$i); for(i = 1; i <= NF; i++) { printf "\"%s\"",$i; if(i < NF) printf "," }; printf "\n" }' 

"flop","flap"""" 
4

@伊格纳西奥 - 巴斯克斯 - 艾布拉姆斯的蟒蛇的解决方案是伟大的!对于那些希望解析分隔符其他选项卡的人来说,该库实际上允许您设置任意分隔符。下面是我修改的版本来处理竖线分隔的文件:如果你想整个TSV文件转换成csv文件

import sys 
import csv 

pipein = csv.reader(sys.stdin, delimiter='|') 
commaout = csv.writer(sys.stdout, dialect=csv.excel) 
for row in pipein: 
    commaout.writerow(row) 
4
  • $ cat data.tsv | tr "\\t" "," > data.csv 
    

  • 如果你想省略一些字段:

    $ cat data.tsv | cut -f1,2,3 | tr "\\t" "," > data.csv 
    

    上面的命令会将data.tsv文件转换为仅包含前三个字段的data.csv文件

+1

很好:) – 2017-07-25 03:50:33

相关问题