【问题标题】:Convert csv file to txt file将csv文件转换为txt文件
【发布时间】:2015-12-11 19:57:20
【问题描述】:

我正在使用 perl 使用以下命令将逗号分隔的文件转换为制表符分隔的文件:

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 来执行此操作?

【问题讨论】:

标签: python bash perl csv


【解决方案1】:

您需要正则表达式来帮助您。在 python 中,它只是:

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

【讨论】:

    【解决方案2】:

    在python中

    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)
    

    【讨论】:

      【解决方案3】:

      基于 rll 的正则表达式答案,您可以将它变成一个 perl oneliner,就像您现在正在做的那样

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

      【讨论】:

        【解决方案4】:

        这会起作用的:

        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
        

        将括号放入要拆分的模式中,将捕获的分隔符与拆分元素一起返回,并有效地将包含引号的字符串分隔为单独的列表元素,当检测到引号时可以区别对待。您只需去掉引号字符串的逗号和引号,并替换其他元素中的制表符,然后使用制表符连接元素(以便带引号的字符串与制表符连接到其他已制表符的字符串。

        【讨论】:

        • 不如@cts 的答案高效,因为它使用了 foreach 循环,但它确实删除了引号。这个主题的另一个版本:perl -e '$sep=",";while(&lt;STDIN&gt;){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 "Changed $sep to tab on $. lines\n"' &lt; csvfile.csv &gt; tabfile.tab
        【解决方案5】:

        Text::CSV 模块正是您要找的。解析 CSV 文件的时候有很多注意事项,你真的不想自己处理所有这些。

        【讨论】:

          【解决方案6】:

          在 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 );
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-08-05
            相关资源
            最近更新 更多