Frage

Ich habe dieses Perl-Skript dabei gefunden Migration meiner SQLite-Datenbank nach MySQL

Ich habe mich gefragt (da ich Perl nicht kenne), wie man das in Python umschreiben könnte?

Bonuspunkte für die kürzeste (Code-)Antwort :)

bearbeiten:Entschuldigung, ich meinte den kürzesten Code, nicht unbedingt die kürzeste Antwort

#! /usr/bin/perl

while ($line = <>){
    if (($line !~  /BEGIN TRANSACTION/) && ($line !~ /COMMIT/) && ($line !~ /sqlite_sequence/) && ($line !~ /CREATE UNIQUE INDEX/)){

        if ($line =~ /CREATE TABLE \"([a-z_]*)\"(.*)/){
                $name = $1;
                $sub = $2;
                $sub =~ s/\"//g; #"
                $line = "DROP TABLE IF EXISTS $name;\nCREATE TABLE IF NOT EXISTS $name$sub\n";
        }
        elsif ($line =~ /INSERT INTO \"([a-z_]*)\"(.*)/){
                $line = "INSERT INTO $1$2\n";
                $line =~ s/\"/\\\"/g; #"
                $line =~ s/\"/\'/g; #"
        }else{
                $line =~ s/\'\'/\\\'/g; #'
        }
        $line =~ s/([^\\'])\'t\'(.)/$1THIS_IS_TRUE$2/g; #'
        $line =~ s/THIS_IS_TRUE/1/g;
        $line =~ s/([^\\'])\'f\'(.)/$1THIS_IS_FALSE$2/g; #'
        $line =~ s/THIS_IS_FALSE/0/g;
        $line =~ s/AUTOINCREMENT/AUTO_INCREMENT/g;
        print $line;
    }
}

Etwas zusätzlicher Code war erforderlich, um die SQLite-Datenbank erfolgreich zu migrieren (verarbeitet eine Zeile „Create Table“-Anweisungen, Fremdschlüssel, behebt einen Fehler im Originalprogramm, der leere Felder konvertierte). '' Zu \'.

ICH habe den Code zur Frage „Migration meiner SQLite-Datenbank zu MySQL“ gepostet

War es hilfreich?

Lösung

Hier ist eine ziemlich wörtliche Übersetzung nicht mit dem Minimum von offensichtlichen Stiländerungen (alle Codes in eine Funktion setzen, string mit, anstatt wieder Operationen, wenn möglich).

import re, fileinput

def main():
  for line in fileinput.input():
    process = False
    for nope in ('BEGIN TRANSACTION','COMMIT',
                 'sqlite_sequence','CREATE UNIQUE INDEX'):
      if nope in line: break
    else:
      process = True
    if not process: continue
    m = re.search('CREATE TABLE "([a-z_]*)"(.*)', line)
    if m:
      name, sub = m.groups()
      line = '''DROP TABLE IF EXISTS %(name)s;
CREATE TABLE IF NOT EXISTS %(name)s%(sub)s
'''
      line = line % dict(name=name, sub=sub)
    else:
      m = re.search('INSERT INTO "([a-z_]*)"(.*)', line)
      if m:
        line = 'INSERT INTO %s%s\n' % m.groups()
        line = line.replace('"', r'\"')
        line = line.replace('"', "'")
    line = re.sub(r"([^'])'t'(.)", r"\1THIS_IS_TRUE\2", line)
    line = line.replace('THIS_IS_TRUE', '1')
    line = re.sub(r"([^'])'f'(.)", r"\1THIS_IS_FALSE\2", line)
    line = line.replace('THIS_IS_FALSE', '0')
    line = line.replace('AUTOINCREMENT', 'AUTO_INCREMENT')
    print line,

main()

Andere Tipps

Alex Martelli Lösung über funktioniert gut, braucht aber einige Korrekturen und Ergänzungen :

In den Zeilen regulären Ausdruck Substitution verwenden, das Einsetzen der angepaßten Gruppen muß doppelt entkommen sein oder die Ersatzzeichenfolge muss mit r vorangestellt werden, zu markieren ist als regulärer Ausdruck:

line = re.sub(r"([^'])'t'(.)", "\\1THIS_IS_TRUE\\2", line)

oder

line = re.sub(r"([^'])'f'(.)", r"\1THIS_IS_FALSE\2", line)

Auch sollte diese Zeile vor Druck hinzugefügt werden:

line = line.replace('AUTOINCREMENT', 'AUTO_INCREMENT')

Letzte, die Spaltennamen in erstellen Aussagen sollten in MySQL Backticks sein. Fügen Sie diese in Zeile 15:

  sub = sub.replace('"','`')

Hier ist das komplette Skript mit Änderungen:

import re, fileinput

def main():
  for line in fileinput.input():
    process = False
    for nope in ('BEGIN TRANSACTION','COMMIT',
                 'sqlite_sequence','CREATE UNIQUE INDEX'):
      if nope in line: break
    else:
      process = True
    if not process: continue
    m = re.search('CREATE TABLE "([a-z_]*)"(.*)', line)
    if m:
      name, sub = m.groups()
      sub = sub.replace('"','`')
      line = '''DROP TABLE IF EXISTS %(name)s;
CREATE TABLE IF NOT EXISTS %(name)s%(sub)s
'''
      line = line % dict(name=name, sub=sub)
    else:
      m = re.search('INSERT INTO "([a-z_]*)"(.*)', line)
      if m:
        line = 'INSERT INTO %s%s\n' % m.groups()
        line = line.replace('"', r'\"')
        line = line.replace('"', "'")
    line = re.sub(r"([^'])'t'(.)", "\\1THIS_IS_TRUE\\2", line)
    line = line.replace('THIS_IS_TRUE', '1')
    line = re.sub(r"([^'])'f'(.)", "\\1THIS_IS_FALSE\\2", line)
    line = line.replace('THIS_IS_FALSE', '0')
    line = line.replace('AUTOINCREMENT', 'AUTO_INCREMENT')
    if re.search('^CREATE INDEX', line):
        line = line.replace('"','`')
    print line,

main()

Hier ist eine etwas bessere Version des Originals.

#! /usr/bin/perl
use strict;
use warnings;
use 5.010; # for s/\K//;

while( <> ){
  next if m'
    BEGIN TRANSACTION   |
    COMMIT              |
    sqlite_sequence     |
    CREATE UNIQUE INDEX
  'x;

  if( my($name,$sub) = m'CREATE TABLE \"([a-z_]*)\"(.*)' ){
    # remove "
    $sub =~ s/\"//g; #"
    $_ = "DROP TABLE IF EXISTS $name;\nCREATE TABLE IF NOT EXISTS $name$sub\n";

  }elsif( /INSERT INTO \"([a-z_]*)\"(.*)/ ){
    $_ = "INSERT INTO $1$2\n";

    # " => \"
    s/\"/\\\"/g; #"
    # " => '
    s/\"/\'/g; #"

  }else{
    # '' => \'
    s/\'\'/\\\'/g; #'
  }

  # 't' => 1
  s/[^\\']\K\'t\'/1/g; #'

  # 'f' => 0
  s/[^\\']\K\'f\'/0/g; #'

  s/AUTOINCREMENT/AUTO_INCREMENT/g;
  print;
}

Alle Skripte auf dieser Seite können nicht mit einfachem SQLite3 umgehen:

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE Filename (
  FilenameId INTEGER,
  Name TEXT DEFAULT '',
  PRIMARY KEY(FilenameId) 
  );
INSERT INTO "Filename" VALUES(1,'');
INSERT INTO "Filename" VALUES(2,'bigfile1');
INSERT INTO "Filename" VALUES(3,'%gconf-tree.xml');

Keiner konnte „table_name“ in den richtigen „table_name“ von MySQL umformatieren.Einige haben einen leeren Zeichenfolgenwert durcheinander gebracht.

Ich bin nicht sicher, was so schwer ist, um dies zu verstehen, dass es über eine abfällige Bemerkung wie in Ihrem Kommentar erfordert. Beachten Sie, dass <> wird der Diamant Operator genannt. s/// ist die Substitution Operator und // ist das Match Operator m//.

Basierend auf http://docs.python.org/dev/howto/regex .html ...

  1. Ersetzen $line =~ /.*/ mit re.search(r".*", line).
  2. $line !~ /.*/ ist nur !($line =~ /.*/).
  3. Ersetzen $line =~ s/.*/x/g mit line=re.sub(r".*", "x", line).
  4. Ersetzen $1 durch $9 innen re.sub mit \1 durch \9 sind.
  5. außerhalb eines Unter, speichern den Rückgabewert, das heißt m=re.search() und $1 mit dem Rückgabewert von m.group(1) ersetzen.
  6. Für "INSERT INTO $1$2\n" Insbesondere können Sie "INSERT INTO %s%s\n" % (m.group(1), m.group(2)) tun.

eigentliches Problem ist, wissen Sie eigentlich, wie die Datenbank zu migrieren? Was präsentiert wird, ist lediglich eine Suche und ersetzen Schleife.

Kürzeste? Die Tilde bedeutet eine Regex in Perl. „Import re“ und gehen von dort aus. Die einzigen wesentlichen Unterschiede sind, dass Sie \ 1 und \ 2 anstelle von $ 1 verwenden werden und $ 2, wenn Sie Werte zuweisen, und Sie werden für die Verwendung von% s sein, wenn Sie regexp Matches innerhalb von Zeichenketten sind zu ersetzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top