2017-06-07 3 views
0

Ich habe eine CSV-Zeile wie folgt aus:Wie CSV mit Pgloader oder PostgreSQL-Kopie zu analysieren, wenn es ein n (Zeilenumbruch) in Anführungszeichen gibt?

"aaa"|"bbb"|"ccc"|"dddd 
eeeee" 

Ich möchte diese Daten importieren, mit pgloader (http://pgloader.io/) oder PostgreSQL COPY (https://www.postgresql.org/docs/9.6/static/sql-copy.html). Mein Problem hier ist die Tatsache, dass es gemäß den CSV-Standards möglich ist, einen Zeilenumbruch (\ n) innerhalb eines zitierten Feldwertes zu haben. Aber pgloader und auch der COPY-Befehl behandeln es wie eine brandneue Datenzeile, statt einer Spalte mit Zeilenumbruch im Inneren.

COPY schema.table (
    col_aaa, 
    col_bbb, 
    col_ccc, 
    col_ddd 
) 
    FROM 'file.csv' WITH DELIMITER '|' ENCODING 'LATIN1' CSV; 

Mein Befehl COPY Mein pgloader Befehl

LOAD CSV 
FROM 'file.csv' 
INTO postgresql://user:[email protected]: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; $$; 

Ich habe viel von den PostgreSQL-Dokumenten suchen und auch von Google.

Das einzige, was ich gefunden habe, war das: Parsing CSV file with \n in double quoted fields aber awk ist zu langsam für eine Datei mit mehr als 1 Million Zeilen.

Irgendwelche Hinweise, wie es geht?

Meine Präferenz ist für pgloader, aber ich kann die Verwendung von sed oder perl als Regex-Agent zur Behandlung von Datei in einem Linux-Shell-Skript akzeptieren.

Irgendwelche Hinweise, wie es geht?

+0

Sie haben die Spaltennummern in jeder Zeile zu prüfen, ob es kleiner als die tatsächliche Anzahl der Spalten ist, sollten Sie nächste Zeile zur aktuellen Zeile hinzufügen und erneut prüfen. – AbhiNickz

+0

Sorry @AbhiNickz Ich kann nicht sehen, wie diese Idee das Problem löst. Die Sache ist, dass ich einen zusätzlichen Zeilenumbruch innerhalb der Felddaten habe, und das Hinzufügen eines neuen scheint nicht zu helfen. –

+0

Bitte überprüfen Sie die Antwort, ich füge keine neue Zeile hinzu, ich bin im Grunde verkettet die Zeilen, die wegen ** \ n ** in zwei Zeilen aufgeteilt sind. – AbhiNickz

Antwort

0

Das Problem war, dass am Ende der Zeile gab es ein \ r \ n. Und um das zu lösen, entfernte ich das \ r nur aus dem Zeilenumbruch innerhalb der Daten.

So konnte pgloader den Job erledigen.

Ich habe das getan, indem Sie eine Zeile Perl verwenden.

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 command line multi-line replace

0

Um Ihnen eine Idee zu geben, dieses Problem zu lösen, schreibe ich dieses Beispiel.

Ich habe gerade angenommen, dass die Datei nur 4 Spalten enthalten wird und nur 1 Zeilenumbruch enthalten wird. Wenn dies nicht der Fall ist, müssen Sie dies ändern.

Eingabedatei:

"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); 

Ausgabedatei:

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

Ändern Sie diese EXA Mple zu Ihrem Bedarf. Hoffe, das hilft.

Verwandte Themen