2015-09-15 142 views
-1

我用perl轉換一個逗號分隔的文件,以製表符分隔文件,使用此命令:轉換CSV文件到txt文件

perl -e ' $sep=","; while(<>) { s/\Q$sep\E/\t/g; print $_; } warn "Changed $sep to tab on $. lines\n" ' csvfile.csv > tabfile.tab 

然而,我的文件有,我不希望有額外的逗號在特定列中分隔。這裏是和例子我的文件:

ADNP, "descript1, descript2", 1 
PTB, "descriptA, descriptB", 5 

我只想逗號的報價之外轉換爲製表符像這樣:

ADNP descript1, descript2 1 
PTB descriptA, descriptB 5 

反正是有去有是Perl,Python中這樣做,還是bash?

+4

http://perlmaven.com/how-to-read-a-csv-file-using-perl – 123

回答

3

在Perl微不足道的,使用Text::CSV:。

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Text::CSV; 

#configure our read format using the default separator of "," 
my $input_csv = Text::CSV->new({ binary => 1 }); 
#configure our output format with a tab as separator. 
my $output_csv = Text::CSV->new({ binary => 1, sep_char => "\t", eol => "\n" }); 

#open input file 
open my $input_fh, '<', "sample.csv" or die $!; 
#iterate input file - reading in 'comma separated' 
#printing out (to stdout -can use filehandle) tab separated. 
while (my $row = $input_csv->getline($input_fh)) { 
    $output_csv->print(\*STDOUT, $row); 
} 
0

你需要正則表達式來幫助你。在蟒蛇它只會是:

>>> re.split(r'(?!\B"[^"]*),(?![^"]*"\B)', 'ADNP, "descript1, descript2", 1' 
['ADNP', ' "descript1, descript2"', ' 1'] 
1

在蟒蛇

import csv 

with open('input', 'rb') as inf: 
    reader = csv.reader(inf) 
    with open('output', 'wb') as out: 
     writer = csv.writer(out, delimiter='\t') 
     writer.writerows(reader) 
0

建立關RLL的正則表達式的答案,你可以把它變成一個Perl oneliner像你currenly做

perl -ne 'BEGIN{$,="\t";}@a=split(/(?!\B"[^"]*),(?![^"]*"\B)/);print @a' csvfile.csv > tabfile.tab 
0

這將工作:

perl -e '$sep=","; while(<STDIN>) { @data = split(/(\Q$sep\E?\s*"[^"]+"\s*\Q$sep\E?)/); foreach(@data){if(/"/){s/^\Q$sep\E\s*"//;s/"\s*\Q$sep\E$//;}else{s/\Q$sep\E/\t/g;}}print(join("\t",@data));} warn "Changed $sep to tab on $. lines\n"' <csvfile.csv> tabfile.tab 

推杆將模式中的父元素拆分,將捕獲的分隔符與拆分元素一起返回,並將包含引號的字符串有效地分離爲單獨的列表元素,在檢測到引號時可以對它們進行不同處理。您只需剝離引用字符串的逗號和引號,並替換其他元素中的選項卡,然後將元素與選項卡結合在一起(以便引用的字符串與選項卡結合到其他已有的選項卡式字符串中。

+0

不像@ cts的答案那樣高效,因爲它使用了foreach循環,但它確實刪除了引號。這個主題的另一個版本:'perl -e'$ sep =「,」; while(){print(join(「\ t」,map {if(/「/){s/^ \ Q $ sep \ E \ s *「// // s /」\ s * \ Q $ sep \ E $ //;} else {s/\ Q $ sep \ E/\ t/g;} $ _} split(/(\ Q $ sep \ E?\ s *「[^」] +「\ s * \ Q $ sep \ E?)/)));} warn」將$ sep更改爲$。lines上的選項卡\ n「' tabfile.tab' – hepcat72

0

Text::CSV模塊是你要找的內容有很多解析CSV文件時注意事項,你真的不希望處理所有這些自己