我有一条这样的csv线路:
"aaa"|"bbb"|"ccc"|"dddd
eeeee"我想使用pgloader (http://pgloader.io/)或PostgreSQL COPY (https://www.postgresql.org/docs/9.6/static/sql-copy.html)导入这些数据。我在这里的问题是,根据CSV标准,在引用的字段值中有一个行间隔(\n)是可能的。但是pgloader和COPY命令将它视为一个全新的数据行,而不是在其中包含行中断的一列。
COPY schema.table (
col_aaa,
col_bbb,
col_ccc,
col_ddd
)
FROM 'file.csv' WITH DELIMITER '|' ENCODING 'LATIN1' CSV;我的复制命令我的pgloader命令
LOAD CSV
FROM 'file.csv'
INTO postgresql://user:password@host:5432/database?schema.table (col_aaa, col_bbb, col_ccc, col_ddd)
WITH
skip header = 0,
fields optionally enclosed by '"',
fields escaped by double-quote,
fields terminated by '|'
SET client_encoding to 'latin1'
BEFORE LOAD DO
$$ TRUNCATE anac.aerodromos_csv RESTART IDENTITY; $$;我从PostgreSQL文档中搜索了很多东西,也从谷歌搜索了很多东西。
我发现的唯一一件事是:Parsing CSV file with \n in double quoted fields但是awk太慢了,对于一个超过100万行的文件来说。
对怎么做有什么建议吗?
我的首选是pgloader,但我可以接受使用sed或perl作为regex代理来处理linux脚本中的文件。
有怎么做的线索吗?
发布于 2017-06-21 19:49:33
问题是,在行的末尾有一个\r\n,为了解决这个问题,我只从数据中的行中断中删除\r。
这样,pgloader就能够完成这项工作。
我通过使用一行perl实现了这一点。
perl -0777 -pi -e 's/(?<="[^"|])*(?<!["|])\r\n(?=[^"]*")/\n/smg' $csv_file_name # O -0777 is explained at em https://stackoverflow.com/questions/9670426/perl-command-line-multi-line-replace发布于 2017-06-08 07:27:26
为了给你一个解决这个问题的想法,我正在写这个例子。
我刚刚假设该文件将只包含4列,并且只包含1行中断。如果不是这样的话,那么您需要改变这种情况。
输入文件:
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"dddd
eeeee"
"aaa"|"bbb"|"cc
c"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"b
bb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"a
aa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"dddd
eeeee"script.pl
#!/usr/bin/perl
use strict; use warnings; use Data::Dumper;
open ( my $RFH, '<', 'input.io' ) or die ($!);
open ( my $WFH, '>', 'output.o' ) or die ($!);
my $line_break = 0;
my $old_line = '';
while ( my $line = <$RFH> ) {
chomp($line);
if ( ! $line_break ){
my @columns = split( /\|/, $line );
if ( scalar( @columns ) == 4 && $columns[3] =~ m/"$/ ){
print $WFH $line."\n";
}
else{
$line_break = 1;
$old_line = $line;
next;
}
}
else{
$line = $old_line . $line;
$old_line = '';
$line_break = 0;
print $WFH $line."\n";
}
}
close($RFH);
close($WFH);输出文件:
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"
"aaa"|"bbb"|"ccc"|"ddddeeeee"将此示例更改为您的需要。希望这能有所帮助。
https://stackoverflow.com/questions/44419059
复制相似问题