【问题标题】:Replace all occurences of regex string with info from input+string用输入+字符串中的信息替换所有出现的正则表达式字符串
【发布时间】:2015-11-25 13:30:22
【问题描述】:

我有一个 sql nodata 转储,我需要通过它并替换每个 create table 查询的引擎部分。我被卡住的地方是我需要在每个要替换的字符串中为相应的表提及表名

假设文件如下

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)

我被困在如何将每个表的表名放入替换的字符串中。任何帮助表示赞赏。

【问题讨论】:

  • 如果您将整个文件作为一个字符串读取(如果它不大),我建议将CREATE TABLE) ENGINE= 之间的所有子字符串抓取到一些 table_block 中(您可以使用此正则表达式 - CREATE\s+TABLE\s+`[^`]*`\s+\([^)]*(?:\)(?!\s+ENGINE=)[^)])*\)\s+ENGINE=.* (demo here),然后使用 re.sub(r"\bENGINE\b.*", "ENGINE-myreplacedstring-", table_block)
  • 我遇到的问题是将表名添加到每个表的 myreplacedstring 的末尾

标签: python regex federated-storage-engine


【解决方案1】:

您的解决方案肯定会奏效,但您可以通过反向引用更快地做到这一点。我对此进行了测试,并且可以正常工作(您可以将其设为单线,但这样更具可读性):

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)

【讨论】:

  • 一定是我做错了,我试过了,但报错pastebin.com/i6k27B6a
  • 确实,我忘记了后视必须有固定的长度,所以我们不能在其中使用“*”,这个错误是合法的。我们可以通过将未知组从后视中取出并将其再次添加到替换字符串中来解决这个问题,我将编辑我的答案。
  • 您的解决方案不仅简洁易读,而且更坚固,因为它不关心换行符。
【解决方案2】:

想通了。不确定这是多么优雅或牢不可破,但它似乎适用于我的情况(使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多