Перевод Perl в Python
Я нашел этот Perl script, в то время как перенастроил мою базу данных SQLite в mysql
Мне было интересно (поскольку я не знаю Perl), как можно переписать это в Python?
Бонусные баллы за самый короткий (код) ответ:)
edit: извините, я имел в виду самый короткий код, а не строго короткий ответ
#! /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;
}
}
Для успешной миграции базы данных sqlite необходим дополнительный код (обрабатывает одну строку. Создает операторы таблицы, внешние ключи, исправляет ошибку в исходной программе, которая преобразует пустые поля ''
в \'
.
I разместил код при миграции моей базы данных SQLite в mysql Вопрос
Ответы
Ответ 1
Здесь довольно буквальный перевод с минимальным очевидным изменением стиля (помещая весь код в функцию, используя, по возможности, строку, а не повторять операции).
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
Решение Alex Martelli выше работает хорошо, но нуждается в некоторых исправлениях и дополнениях:
В строках, использующих замещение регулярных выражений, вставка согласованных групп должна быть двойным экранированием ИЛИ заменяющая строка должна иметь префикс r для маркировки как регулярное выражение:
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')
Наконец, имена столбцов в операторах создания должны быть обратными в MySQL. Добавьте это в строку 15:
sub = sub.replace('"','`')
Здесь полный script с изменениями:
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
Вот немного лучшая версия оригинала.
#! /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
все сценарии на этой странице не могут иметь дело с простым sqlite3:
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_name" в правильное mysql `table_name`. Некоторое испорченное пустое строковое значение.
Ответ 5
На основе http://docs.python.org/dev/howto/regex.html...
- Замените
$line =~ /.*/
на re.search(r".*", line)
.
-
$line !~ /.*/
- это просто !($line =~ /.*/)
.
- Замените
$line =~ s/.*/x/g
на line=re.sub(r".*", "x", line)
.
- Замените
$1
на $9
внутри re.sub
на \1
через \9
соответственно.
- Вне вспомогательного устройства сохраните возвращаемое значение, т.е.
m=re.search()
, и замените $1
на возвращаемое значение m.group(1)
.
- Для
"INSERT INTO $1$2\n"
в частности, вы можете сделать "INSERT INTO %s%s\n" % (m.group(1), m.group(2))
.
Ответ 6
Я не уверен, что так трудно понять по этому поводу, что для него требуется замечание, как в вашем комментарии выше. Заметим, что <>
называется оператором алмаза. s///
- оператор подстановки, а //
- оператор сопоставления m//
.
Ответ 7
Кратчайший? Тильда обозначает регулярное выражение в perl. "import re" и перейти оттуда. Единственные ключевые отличия в том, что вы будете использовать \1 и\2 вместо $1 и $2 при назначении значений, и вы будете использовать% s для замены регулярных совпадений внутри строк.
Ответ 8
Реальная проблема: знаете ли вы, как переносить базу данных? Представленный результат представляет собой просто цикл поиска и замены.