2015-11-25 49 views
0

我有一個sql無數據轉儲,我需要通過它並替換每個創建表查詢的引擎部分。我在哪裏卡住的一點是,我需要在每個串我與替換爲相應的表用輸入+字符串中的信息替換所有正則表達式字符串

假設一個文件,如下

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) 

我被困在如何讓每個表的表名到我替換的字符串。任何幫助表示讚賞。

+0

如果你把整個文件看作一個字符串(如果它不是很大),我建議把'CREATE TABLE'和')ENGINE ='之間的所有子字符串都轉換成一些* table_block * s(你可以使用這個正則表達式 - CREATE \ s +表\ S + \'[^ \'] * \'\ S + \([^)] *(?:\)(?!\ S + ENGINE =)[^)])* \)\ S + ENGINE = *'([demo here](https://regex101.com/r/aF3iP6/1)),然後使用're.sub(r「\ bengine \ b。*」,「ENGINE-myreplacedstring-」 table_block)'。 –

+0

我遇到的問題是將表名添加到每個表的myreplacedstring的末尾 – AdrianBR

回答

1

您的解決方案肯定會有效,但您可以通過反向引用更快地完成。我測試了這一點,它的工作原理(你可以把一個班輪但it's更具可讀性這種方式):

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) 
+0

我一定在做錯了,我試了一下,但得到了一個錯誤http://pastebin.com/i6k27B6a – AdrianBR

+0

的確,我忘記了look-背後必須有固定的長度,所以我們不能使用'*',這個錯誤是合法的。我們可以通過將外部未知組添加到替換字符串中並將其添加到替換字符串中來解決該問題,我將編輯我的答案。 – Enaid

+0

工程就像一個魅力,謝謝你回來! – AdrianBR

0

想通了。不知道這是多麼優雅或牢不可破,但它似乎對我的情況很好(採取MySQL無數據轉儲,用聯合連接字符串替換引擎,以輕鬆創建從一個數據庫到另一個數據庫的完整聯邦數據庫)。

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