*Markus: Probleme beim Escapen von Parametern

Hallo,

ich habe eine Länderliste, die ich als SQL-Script in eine DB einlesen will.
Dazu dachte ich an eine einzeilige Perlanweisung in der Bash, dass mir das SQL-Script erzeugen soll.
Bisher teste ich noch in der Ausgabe, was bis auf ein paar verlorene Zeilen ja schon ganz gut funktioniert.

zB wird aus

SG Singapur Singapore
SK Slowakei Slovakia
SI Slowenien Slovenia

durch den Ausdruck

  
$ perl -nle 'print "insert into (land, land_de, land_en) values ($1, $2, $3);" while (/^(\w{2})\t([\wÄÖÜäöü]+)\t(\w+)/g)' < insert_laender.sql  

der Befehl

  
insert into (land, land_de, land_en) values (SG, Singapur, Singapore);  
insert into (land, land_de, land_en) values (SK, Slowakei, Slovakia);  
insert into (land, land_de, land_en) values (SI, Slowenien, Slovenia);  

ich habe aber noch massive Probleme damit, die Parameter $1, $2, und $3 unter einfache Anführungszeichen zu setzen. Ein '$1' oder \'$1\' liefert nicht die gewünschten Ergebnisse.
Ich versuchte auch den String zu verketten:

  
$ perl -nle 'print "insert into (land, land_de, land_en) values ('". $1 ."', '".$2."', '".$3."');" while (/^(\w{2})\t([\wÄÖÜäöü]+)\t(\w+)/g)' < insert_laender.sql  

Dabei kommt aber so etwas heraus:

insert into (land, land_de, land_en) values (.  ., .., ..);  

Irgendwie komme ich wohl irgendwo durcheinander, aber wo?

Markus

  1. insert into (land, land_de, land_en) values (SG, Singapur, Singapore);
    insert into (land, land_de, land_en) values (SK, Slowakei, Slovakia);
    insert into (land, land_de, land_en) values (SI, Slowenien, Slovenia);

    
    >   
    > ich habe aber noch massive Probleme damit, die Parameter $1, $2, und $3 unter einfache Anführungszeichen zu setzen. Ein \'$1\' oder \\'$1\\' liefert nicht die gewünschten Ergebnisse.  
      
    Benutzt du nicht DBI?  
    Dafür bieten sich [Platzhalter](http://search.cpan.org/~timb/DBI/DBI.pm#Placeholders_and_Bind_Values) an, dann passiert das automatisch.  
      
    Struppi.
    
    1. Hallo,

      das hat nichts mit meinem Problem zu tun, denn diese Rohdaten werden in eine Lookup-Tabelle per PostgreSQLs "\i script.sql" eingespielt.

      Markus

      1. das hat nichts mit meinem Problem zu tun, denn diese Rohdaten werden in eine Lookup-Tabelle per PostgreSQLs "\i script.sql" eingespielt.

        Du kannst auch direkt DBI::quote benutzen um die Daten zu maskieren.

        Struppi.

        1. Moin Moin!

          »» das hat nichts mit meinem Problem zu tun, denn diese Rohdaten werden in eine Lookup-Tabelle per PostgreSQLs "\i script.sql" eingespielt.

          Du kannst auch direkt DBI::quote benutzen um die Daten zu maskieren.

          ... was im allgemeinen das Caching von SQL-Statements nachhaltig sabotiert, gerne mal vergessen wird, und so außerdem noch zu einer Anfälligkeit für SQL Injection führt. Generell gilt: Inline-Werte sind böse, Platzhalter sind gut.

          In diesem speziellen Fall könnte das tatsächlich funktionieren, wobei psql vermutlich auch nochmal die eine oder andere abweichende oder zusätzliche Quoting-Regel hat.

          Ich frage mich, warum Markus die Daten nicht einfach per Perl in die DB schreibt, wenn er sie ohnehin schon in Perl aufbereitet. DBI bietet alle notwendigen Voraussetzungen.

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. Hallo,

            Ich frage mich, warum Markus die Daten nicht einfach per Perl in die DB schreibt, wenn er sie ohnehin schon in Perl aufbereitet. DBI bietet alle notwendigen Voraussetzungen.

            Eigentlich ist Perl hier nur Mittel zum Zweck. Zuerst wollte ich es ja mit sed erledigen, aber sed scheint nicht so detailiert reguläre Ausdrücke zu beherrschen.

            Markus

            1. Wenn ich die Single Quotes folgendermaßen escape, funktioniert es:

              ... values (''$1'' ...

              Markus

              1. Moin Moin!

                Wenn ich die Single Quotes folgendermaßen escape, funktioniert es:

                ... values (''$1'' ...

                Wie gesagt, die sauberere Variante wäre, DBI mit Platzhaltern zu benutzen. Dein Mechanismus fällt ÜBELST auf die Schnauze, sobald $1 Single Quotes und ggf. Backslashes enthält.

                Ansatz (ungeprüft):

                  
                #!/usr/bin/perl -w  
                  
                # Aufruf: script.pl < daten.txt  
                  
                use strict;  
                use DBI;  
                  
                my $dbh=DBI->connect('dbi:Pg:DATENBANK','USER','PASSWORD',{ RaiseError => 1 });  
                ### 1 ###  
                my $sth=$dbh->prepare('insert into FOOBAR (FOO,BAR,BAZ) values (?,?,?)'); #  
                while (<>) {  
                    chomp;  
                    /^(\w+)\t(w+)\t(w+)$/ or next; # ANPASSEN!  
                    $sth->execute($1,$2,$3);  
                }  
                $sth->finish();  
                $dbh->disconnect();  
                
                

                Alexander

                --
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                1. Hallo,

                  zu meiner Schande ist mein Perl auch schon ziemlich eingerostet. =( ich wollte mir jetzt auch nicht die Mühe machen, nachzulesen, wie ich DBI benutze.

                  Markus