解析CSV文件并在Linux中执行转换

时间:2013-06-21 21:55:40

标签: linux unix csv

我有一个包含大量列的大型CSV文件(几个100 MB):

1;18Jun2013;23:58:58;;;l;o;t;s;;;;o;f;;;;;o;t;h;e;r;;;;;c;o;l;u;m;n;s;;;;;

您会看到第二列是我希望格式为%Y-%m-%d的日期,以便在数据库中轻松插入和排序。我相信转换原始数据更容易,更快,而不是以后在数据库中转换。

主脚本使用bash。现在我已经按照以下步骤进行了转换:

  sed -n '2,$p' $TMPF | while read line; do
        begin=$(echo "$line" | cut -d\; -f1)
        origdate=$(echo "$line" | cut -d\; -f2)
        #cache date translations, hash table for the poor
        eval origdateh=h$origdate
        if [ "x${!origdateh}" = "x" ]; then
        # not cached till now, need to call date, then store
            datex=$(date -d "$origdate" +%Y-%m-%d)
            eval h$origdate="$datex"
        else
        # cache hit
            datex=$(eval echo \$h$origdate)
        fi
        end=$(echo "$line" | cut -d\; -f3-)
        echo "$begin;$datex;$end" >> $TMPF2
    done

我使用sed从第二行开始(第一行包含CSV标题)并且我相信所有带有回声和剪切的子shell减慢了速度,所以“哈希表”真的没用多少......

谁可以让这个快点?

2 个答案:

答案 0 :(得分:3)

不要使用bash脚本,而是使用Python脚本。至少,这将更具可读性/可维护性,并且可能更有效。

示例代码看起来像这样(未经测试):

# file: converter.py

import datetime

def convert_line(line):
    # split line on ';'
    line = line.split(';')
    # get the date part (second column)
    # parse date from string
    date = datetime.date.strptime(line[1], '%d%a%Y')
    # convert to desired format
    # replace item in line
    line[1] = date.strftime('%Y-%m-%d')
    # return converted line
    return ';'.join(line)

while True:
    print convert_line(raw_input())

现在你做的就是:

cat file.csv | python converter.py > file_converted.csv

替代实施:

# file: converter_2.py

import datetime

def convert_line(line):
    # split line on ';'
    line = line.split(';')
    # get the date part (second column)
    # parse date from string
    date = datetime.date.strptime(line[1], '%d%a%Y')
    # convert to desired format
    # replace item in line
    line[1] = date.strftime('%Y-%m-%d')
    # return converted line
    return ';'.join(line)

with open('file.csv') as infile, open('file_converted.csv', 'w+') as outfile:
    outfile.writelines(convert_line(line) for line in infile)

使用示例:

python converter_2.py

如果你的csv中有一些标题行,你当然不能用这个函数转换它们。

答案 1 :(得分:1)

谢谢,我尝试了第一个例子,当从bash脚本中调用时,以下似乎工作正常。

# file: converter.py
import datetime
def convert_line(line):
    # split line on ';'
    line = line.split(';')
    # get the date part (second column)
    # parse date from string
    date = datetime.datetime.strptime(line[1], '%d%b%Y')
    # convert to desired format
    # replace item in line
    line[1] = date.strftime('%Y-%m-%d')
    # return converted line
    return ';'.join(line)
while True:
    try:
        print convert_line(raw_input())
    except (EOFError):
        break

使用

tail +2 FILE | python csvconvert.py > xxx

跳过标题。