代码之家  ›  专栏  ›  技术社区  ›  Jiaaro

将Perl转换为Python

  •  21
  • Jiaaro  · 技术社区  · 15 年前

    migrating my SQLite database to mysql

    最短(代码)答案的奖励积分:)

    编辑 :对不起,我指的是最短的代码,不是严格意义上的最短答案

    #! /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;
        }
    }
    

    '' \' .

    posted the code on the migrating my SQLite database to mysql Question

    8 回复  |  直到 7 年前
        1
  •  52
  •   dr jimbob    13 年前

    这是一个非常直译的方法,只需要最少的明显样式更改(将所有代码放入一个函数中,尽可能使用字符串而不是重新操作)。

    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()
    
        2
  •  12
  •   Community CDub    7 年前

    Alex Martelli's solution above

    在使用正则表达式替换的行中,匹配组的插入必须是双转义的,或者替换字符串必须以r作为前缀,以将is标记为正则表达式:

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

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

    此外,打印前应添加此行:

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

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

    以下是经过修改的完整脚本:

    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()
    
        3
  •  8
  •   Brad Gilbert    15 年前

    这是一个稍微好一点的版本。

    #! /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;
    }
    
        4
  •  8
  •   Mickey Mouse    13 年前

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

    没有人能够将“table\u name”重新格式化为正确的mysql的“table\u name”。一些人搞乱了空字符串值。

        5
  •  3
  •   Sinan Ünür    15 年前

    <> 被称为菱形操作符。 s/// 是替换运算符,并且 // 是火柴接线员吗 m// .

        6
  •  3
  •   Brad Gilbert    15 年前

    基于 http://docs.python.org/dev/howto/regex.html

    1. 代替 $line =~ /.*/ 具有 re.search(r".*", line)
    2. $line !~ /.*/ 只是 !($line =~ /.*/) .
    3. $line =~ s/.*/x/g line=re.sub(r".*", "x", line) .
    4. 代替 $1 通过 $9 re.sub 具有 \1 通过 \9 分别地
    5. 在子对象外部,保存返回值,即。 m=re.search() $1 返回值为 m.group(1)
    6. 对于 "INSERT INTO $1$2\n" 具体来说,你可以这样做 "INSERT INTO %s%s\n" % (m.group(1), m.group(2)) .
        7
  •  2
  •   hpavc    15 年前

    真正的问题是您知道如何迁移数据库吗?所呈现的只是一个搜索和替换循环。

        8
  •  1
  •   anschauung    15 年前