在我们的项目中,我们需要将 csv 文件导入到 postgres 中。 有多种类型的文件,这意味着文件的长度会发生变化,因为有些文件的列数较少,有些文件的列数较多。
我们需要一种快速的方法将这个文件导入 postgres。我想使用 postgres 的 COPY FROM,因为处理速度要求非常高(每分钟几乎 150 个文件,每个文件大小为 20K)。
由于文件列号不固定,我需要在将文件传递给 postgres 过程之前对其进行预处理。预处理只是在 csv 中为文件中没有的列添加额外的逗号。
我有两个选项来预处理文件 - 使用 python 或使用 Sed。
我的第一个问题是,预处理文件的最快方法是什么?
第二个问题是,如果我使用 sed,我将如何在第 4、5 个逗号字段后插入一个逗号?
例如如果文件有类似的条目
1,23,56,我们,89,2009-12-06
我需要使用最终输出编辑文件,例如:
1,23,56,我们,,89,,2009-12-06
最佳答案
您是否知道 COPY FROM
让您指定要导入哪些列(以及它们的顺序)?
COPY tablename ( column1, column2, ... ) FROM ...
在 Postgres 级别直接指定要导入哪些列以及以什么顺序导入,通常是最快和最有效的导入方法。
话虽如此,有一种使用sed
(比其他帖子中介绍的方法)更简单(且可移植)的方式来replace an n th occurrence ,例如用双逗号替换第 4 次和第 5 次出现的逗号:
echo '1,23,56,we,89,2009-12-06' | sed -e 's/,/,,/5;s/,/,,/4'
产生:
1,23,56,we,,89,,2009-12-06
请注意,我首先替换了最右边的字段 (#5)。
我看到您也将您的问题标记为与 perl
相关,尽管您没有在问题正文中明确提及 perl
;这是一种可能的实现方式,它使您可以灵活地重新排序或以其他方式处理字段:
echo '1,23,56,we,89,2009-12-06' |
perl -F/,/ -nae 'print "$F[0],$F[1],$F[2],$F[3],,$F[4],,$F[5]"'
还产生:
1,23,56,we,,89,,2009-12-06
与 awk
非常相似,记录一下:
echo '1,23,56,we,89,2009-12-06' |
awk -F, '{print $1","$2","$3","$4",,"$5",,"$6}'
我会把 Python 留给别人。 :)
关于 Perl 示例的小提示:我正在使用 -a
和 -F
选项来自动拆分,所以我有一个较短的命令字符串;但是,这会将换行符嵌入到最后一个字段 ($F[5]
) 中,只要该字段不必在其他地方重新排序就可以了。如果出现这种情况,为了通过 chomp
切换换行符,然后手动 split
最后打印我们自己的换行符 \n
(上面的awk
例子没有这个问题):
perl -ne 'chomp;@F=split/,/;print "$F[0],$F[1],$F[2],$F[3],,$F[4],,$F[5]\n"'
编辑(受 Vivin 启发的想法):
COMMAS_TO_DOUBLE="1 4 5"
echo '1,23,56,we,89,2009-12-06' |
sed -e `for f in $COMMAS_TO_DOUBLE ; do echo "s/,/,,/$f" ; done |
sort -t/ -k4,4nr | paste -s -d ';'`
1,,23,56,we,,89,,2009-12-06
对不起,忍不住了。 :)
关于python - 用于编辑 csv 文件或 Python 的 Sed 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2367338/