Заменить все вхождения строки регулярного выражения на информацию из input+string

У меня есть дамп sql nodata, и мне нужно пройти его и заменить часть двигателя каждого запроса создания таблицы. Дело в том, что я застрял в том, что мне нужно упомянуть имя таблицы в каждой строке, которую я заменяю для соответствующей таблицы

Предполагая файл как ниже

CREATE TABLE `tablename1` (
  -- #columns and keys
) ENGINE=InnoDB AUTO_INCREMENT=5075 DEFAULT CHARSET=utf8;
CREATE TABLE `tablename2` (
  -- #columns and keys
) ENGINE=something AUTO_INCREMENT=55 DEFAULT CHARSET=latin1;

Желаемый результат:

CREATE TABLE `tablename1` (
  -- #columns and keys
) ENGINE=-myreplacedstring/tablename1; -- #table name 1 is appended to this line
CREATE TABLE `tablename2` (
  -- #columns and keys
) ENGINE=myreplacedstring/tablename2; -- #table name 2 is appended to this line

Я старался

fin = open('dump.sql','r')
filedata = fin.read()
fin.close()

newdata = re.sub('(?<=ENGINE).*;', '-myreplacedstring-', filedata)

fout = open('fed_dump.sql','w')
fout.write(newdata)
fout.close()

но это только заменяет строку с фиксированной строкой, независимо от того, какая таблица это.

Я также пытался приблизиться к строке за строкой, чтобы иметь возможность захватывать имя таблицы каждый раз, когда я его пропускаю, но я не уверен, как это сделать.

 with open('dump.sql') as infile, open('dump_fed.sql', 'w') as outfile:
     for line in infile:
         #tablename= if line contains create table, update tablename, else do nothing
         line = re.sub('(?<=ENGINE).*;', '-myreplacedstring-'+tablename, line)
         outfile.write(line)

Я застрял на том, как получить имя таблицы для каждой таблицы в моей замененной строке. Любая помощь приветствуется.

2 ответа

Решение

Ваше решение, безусловно, будет работать, но вы можете сделать это быстрее с помощью обратных ссылок. Я проверил это, и оно работает (вы можете сделать его однострочным, но это будет более читабельным):

pattern = r"CREATE TABLE `(.*?)`(.*?)ENGINE=.*?;"
replace_pattern = r"CREATE TABLE `\1`\2ENGINE=-myreplacedstring-\1;"
newdata = re.sub(pattern, replace_pattern, filedata, flags=re.DOTALL)

С:

  • ´. *? ´, которая не является жадной версией ´.*´
  • "\1" - это обратная ссылка для первой группы захвата для каждого вхождения, например, "tablename1", "tablename2" и т. Д.
  • шаблоны в виде необработанной строки с префиксом ´r´ (что является хорошей привычкой)
  • флаг re.DOTALL, который позволяет "." соответствовать новым строкам

Я предложил перед этим следующее решение, которое является неправильным, потому что предварительные просмотры, сигнализируемые "(?<=...)", должны содержать шаблоны фиксированной длины:

pattern = r"(?<=CREATE TABLE `(.*?)`.*?ENGINE=).*;"
newdata = re.sub(pattern, '-myreplacedstring-\1', filedata)

Догадаться. Не уверен, насколько это элегантно или неразрывно, но в моем случае это работает нормально (взяв дамп mysql nodata, заменив ядро ​​строкой федеративного соединения, чтобы легко создать полную федеративную БД из одной БД в другую).

import re

def gettablename(string, defaultstring):
    if 'CREATE TABLE' in string: 
        return re.search('`(.*)`', string).group(1)
    else: 
        return defaultstring

with open('dump.sql') as infile:
    tablename='def' # do i need this default?
    for line in infile:
        tablename=gettablename(line,tablename)
        line = re.sub('(?<=ENGINE).*;', '-myreplacedstring-'+tablename, line)
        print line
Другие вопросы по тегам