Postgresql 如果存在';双引号中是否有\n(换行符)?

Postgresql 如果存在';双引号中是否有\n(换行符)?,postgresql,csv,postgresql-copy,pgloader,Postgresql,Csv,Postgresql Copy,Pgloader,我有一个csv行,如下所示: "aaa"|"bbb"|"ccc"|"dddd eeeee" 我想使用pgloader()或PostgreSQL COPY()导入此数据。我这里的问题是,根据CSV标准,在引用的字段值中可能有换行符(\n)。但是pgloader和COPY命令将其视为一行全新的数据,而不是一列内部有换行符 COPY schema.table ( col_aaa, col_bbb, col_ccc, col_ddd ) FROM 'file.

我有一个csv行,如下所示:

"aaa"|"bbb"|"ccc"|"dddd
eeeee"
我想使用pgloader()或PostgreSQL COPY()导入此数据。我这里的问题是,根据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文档和谷歌搜索了很多

我发现的唯一一件事是:但是对于一个超过一百万行的文件来说,awk太慢了

有关于如何做的提示吗

我的首选是pgloader,但我可以接受使用sed或perl作为regex代理在linux shell脚本中处理文件


关于如何做,有什么线索吗?

为了给你一个解决这个问题的方法,我写了这个例子

我刚刚假设该文件将只包含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"
"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"
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);
根据您的需要更改此示例。
希望这有帮助。

为了给你一个解决这个问题的方法,我写了这个例子

我刚刚假设该文件将只包含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"
"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"
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);
根据您的需要更改此示例。
希望这能有所帮助。

问题是在行的末尾有一个\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

perl-0777-pi-e的/(?问题是在行的末尾有一个\r\n。为了解决这个问题,我只从数据中的换行符中删除了\r\n

这样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

perl-0777-pi-e的/(?你必须检查每一行中的列数,如果它小于实际列数,你应该在当前行中添加下一行,然后再次检查。抱歉@AbhiNickz我看不出这个想法是如何解决问题的。问题是我在字段数据中有一个额外的换行符,添加一个新的似乎没有帮助。请请确认答案,我不是在添加新行,我基本上是将由于\n原因而被分成两行的行连接起来。您必须检查每行中的列数。如果它小于实际列数,您应该在当前行中添加下一行,然后再次检查。抱歉@AbhiNickz我看不出这个想法如何解决问题。问题是,我在字段数据中有一个额外的换行符,添加一个新的似乎没有帮助。请检查答案,我不是在添加新行,我基本上是将由于\n原因而被分成两行的行连接起来。