Заменить все вхождения строки регулярного выражения на информацию из 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