【问题标题】:fastest way convert tab-delimited file to csv in linux在linux中将制表符分隔的文件转换为csv的最快方法
【发布时间】:2011-02-01 21:03:28
【问题描述】:

我有一个超过 2 亿行的制表符分隔文件。 linux中将其转换为csv文件的最快方法是什么?这个文件确实有多行标题信息,我需要在路上去掉这些信息,但标题行数是已知的。我看到了sedgawk 的建议,但我想知道是否有“首选”选择。

澄清一下,这个文件中没有嵌入标签。

【问题讨论】:

标签: linux csv


【解决方案1】:

如果您担心嵌入式逗号,那么您需要使用更智能的方法。这是一个 Python 脚本,它从标准输入获取 TSV 行并将 CSV 行写入标准输出:

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

【讨论】:

  • 除非您确定没有嵌入的逗号和嵌入的制表符,否则这是一种非常可靠的方法。即使它可能不符合“最快”的标准。
  • 它可能不是“最快的”,但它确实为我处理嵌入的标签和逗号。
  • 这太棒了。我正在编写一个神秘的 sed 脚本来在 bash 中处理这个问题——但这无法与 python csv 库的完整性相媲美。感谢伊格纳西奥,感谢您提供此服务。关于速度 - 易用性和可靠性方式输出速度 - 这当然足够快。 :-)
  • Ignacio,征得您的许可,我想在我的vbin 库中添加您的脚本,并注明出处,作为 tab2csv。
  • @IgnacioVazquez-Abrams:谢谢,伊格纳西奥。 vbin/t2c
【解决方案2】:

如果您只需将所有制表符翻译为逗号字符,tr 可能是最好的选择。

这里的空格是文字标签:

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

当然,如果您在文件中的字符串文字中嵌入了制表符,这也会错误地翻译它们;但是嵌入的文字标签会相当少见。

【讨论】:

  • 更常见的是源代码中嵌入的逗号,然后需要用引号括起来。如果有嵌入式引号,这很麻烦......
  • 感谢tr 的建议。在速度方面与sed 相比如何?假设您想跳过从行号 x 开始的标题并继续到文件的其余部分。有没有办法用tr 来实现这个? (我还应该澄清一下,文件中没有嵌入的逗号。)
  • @andrewj: tr 应该更快,因为它只是逐个字符替换而不是正则表达式匹配。至于跳过标题,最简单的方法就是分两块处理——如果你知道长度,head -n &lt;length&gt; input &gt; output; tail -n +&lt;length+1&gt; input | tr ... &gt;&gt; output;如果你不知道长度,可能是grep -n...
  • @andrew,sed支持音译,也可以使用地址范围。
  • 这是一个不完整的答案;对于 CSV," 必须转换为 "",如果字段包含引号或逗号或换行符,则必须将它们包含在 " 引号中(尽管换行符不会存在于以 TSV 形式呈现的数据中)。
【解决方案3】:
perl -lpe 's/"/""/g; s/^|$/"/g; s/\t/","/g' < input.tab > output.csv

在这类事情上,Perl 通常比 sed、awk 和 Python 更快。

【讨论】:

  • 对我来说最好的答案,只有一点变化,双引号: perl -lpe 's/"/\\"/g; s/^|$/"/g; s/\t/","/g'
  • Perl 万岁!正是我需要的单线。
  • 你是救世主
  • dope,好多年没用这个语言了,完美又快!
【解决方案4】:
  • 如果要将整个 tsv 文件转换成 csv 文件:

    $ cat data.tsv | tr "\\t" "," > data.csv
    

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

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

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

【讨论】:

    【解决方案5】:
    sed -e 's/"/\\"/g' -e 's/<tab>/","/g' -e 's/^/"/' -e 's/$/"/' infile > outfile
    

    该死的评论家,引用一切,CSV 不在乎。

    &lt;tab&gt; 是实际的制表符。 \t 对我不起作用。在 bash 中,使用 ^V 输入。

    【讨论】:

    • tab 可以sed -e 's/"/\\"/g' -e "s/\t/\",\"/g" -e 's/^/"/' -e 's/$/"/' infile &gt; outfile.
    【解决方案6】:

    @ignacio-vazquez-abrams 的 python 解决方案很棒!对于希望解析其他选项卡的分隔符的人,该库实际上允许您设置任意分隔符。这是我处理管道分隔文件的修改版本:

    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)
    

    【讨论】:

      【解决方案7】:

      假设您不想更改标题并假设您没有嵌入标签

      # 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)
      

      【讨论】:

        【解决方案8】:

        您也可以为此使用xsv

        xsv input -d '\t' input.tsv > output.csv
        

        在我对 300MB tsv 文件的测试中,它比 python 解决方案快大约 5 倍(2.5 秒对 14 秒)。

        【讨论】:

        • 感谢您推荐 xsv。一段时间以来,我一直在研究快速 CSV 工具包。
        【解决方案9】:

        以下 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""""
        

        【讨论】:

          【解决方案10】:

          右键单击文件,单击重命名,删除't'并放一个'c'。我实际上不是在开玩笑,大多数 csv 解析器都可以处理制表符分隔符。我现在遇到了这个问题,为了我的目的,重命名工作得很好。

          【讨论】:

            【解决方案11】:

            我认为最好不要 cat 文件,因为它可能会在大文件的情况下产生问题。更好的方法可能是

            $ tr ',' '\t' &lt; csvfile.csv &gt; tabdelimitedFile.txt

            该命令将从 csvfile.csv 获取输入并将结果作为制表符存储在 tabdelimitedFile.txt 中

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-06-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-07-09
              相关资源
              最近更新 更多