Python “问题”;删除“;.sql文件中的行块

Python “问题”;删除“;.sql文件中的行块,python,mysql,Python,Mysql,我正在编写一个脚本,该脚本将从SQL转储中删除一个行块(基本上,清除我们不想恢复的任何表)。我原以为它可以工作,但在尝试将生成的文件恢复到数据库时,我意识到,当脚本重写到文件时,它会丢失更多的行,并且恢复失败。以下是我在这方面微不足道的尝试: #!/usr/bin/python to_keep = [] to_remove = [] f = open("backuptest.sql","r") lines = f.readlines() f.close() ### Function to

我正在编写一个脚本,该脚本将从SQL转储中删除一个行块(基本上,清除我们不想恢复的任何表)。我原以为它可以工作,但在尝试将生成的文件恢复到数据库时,我意识到,当脚本重写到文件时,它会丢失更多的行,并且恢复失败。以下是我在这方面微不足道的尝试:

#!/usr/bin/python

to_keep = []
to_remove = []

f = open("backuptest.sql","r")
lines = f.readlines()

f.close()

### Function to remove lines associated with a table block
def remove_lines(table_name):
    for i in range(0, len(lines)):
        line = lines[i]
        if "structure" in line and table_name in line:
            for j in range(i, len(lines)):
                to_remove.append(lines[j])
                if "UNLOCK TABLES;" in lines[j]:
                    break
        if line not in to_remove:
            to_keep.append(line)
            f.write(line)

print "Finding lines"

f = open("backuptest.sql", "w")
remove_lines("advanced_searches")
f.close()

f = open("backuptest.sql", "w")
remove_lines("test_table2")
f.close()

f = open("backuptest.sql", "w")
remove_lines("test_table3")
f.close()
下面是sql文件的一个块的外观,以供参考:

-- Table structure for table `advanced_searches`
--

DROP TABLE IF EXISTS `advanced_searches`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `advanced_searches` (
  `batch_size` int(11) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `advanced_searches`
--

LOCK TABLES `advanced_searches` WRITE;
/*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;
/*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;
UNLOCK TABLES;
我通过匹配这样一个块中的第一行(包括单词“structure”和表名)开始脚本,然后我尝试从该行通过“UNLOCK TABLES”进行迭代;相反,它会删除脚本中“UNLOCK TABLES”的所有实例;即使是从我不想删除的块中,它还从每个块中删除了以下行“)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8\u unicode\u ci;”(该行其余部分的右括号)

谢谢你的帮助。我会继续努力弥补我错过的东西。

试试
sqlparse
教程中的快速测试:

>>> import sqlparse
>>> sql = "select * from foo; select * from bar;"
>>> res = sqlparse.split(sql)
>>> res
[u'select * from foo;', u'select * from bar;']
应用于SQL脚本:

>>> sql = """-- Table structure for table `advanced_searches`
... --
... 
... DROP TABLE IF EXISTS `advanced_searches`;
... /*!40101 SET @saved_cs_client     = @@character_set_client */;
... /*!40101 SET character_set_client = utf8 */;
... CREATE TABLE `advanced_searches` (
...   `batch_size` int(11) NOT NULL DEFAULT '0'
... ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
... /*!40101 SET character_set_client = @saved_cs_client */;
... 
... --
... -- Dumping data for table `advanced_searches`
... --
... 
... LOCK TABLES `advanced_searches` WRITE;
... /*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;
... /*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;
... UNLOCK TABLES;"""
...
>>> res = sqlparse.split(sql)
>>> res
[u'-- Table structure for table `advanced_searches`\n--\n\nDROP TABLE IF EXISTS `advanced_searches`;',
 u'/*!40101 SET @saved_cs_client     = @@character_set_client */;',
 u'/*!40101 SET character_set_client = utf8 */;',
 u"CREATE TABLE `advanced_searches` (\n  `batch_size` int(11) NOT NULL DEFAULT '0'\n) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;",
 u'/*!40101 SET character_set_client = @saved_cs_client */;',
 u'--\n-- Dumping data for table `advanced_searches`\n--\n\nLOCK TABLES `advanced_searches` WRITE;',
 u'/*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;',
 u'/*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;',
 u'UNLOCK TABLES;']

这提供了正确解析的脚本,最后要做的就是逐个筛选,只挑选那些看起来需要的脚本。这就留给大家了。

最好不要用全局变量代替函数参数-使用参数可以使函数与其环境之间的“耦合”更加清晰。由于您希望从单个文件中删除多个表,因此最好从读取其中的所有行开始,然后将输出行作为新结果传回

def remove_lines(lines, table_name):
   output_lines = []
   for line in lines:
       if line.startswith("-- structure for table") and table_name in line:
           while "UNLOCK TABLE" not in line:
               line = lines.next()
       else:
           output_lines.append(line)
   return output_lines
这个函数应该用一组行和一个表名来调用,它返回一个行列表,必要时可以进一步处理这些行。然后,可以使用最后一组覆盖原始文件(您确定不想保留备份吗?),如下所示:

with open("backuptest.sql","r") as f:
    lines = f.readlines()
for table_name in ("advanced_searches", "test_table2", "test_table1"):
    lines = removelines(lines, table_name)
with open("backuptest.sql", "w") as f
    f.writelines(lines)

从您的示例输入中,您希望删除哪些内容?
with open("backuptest.sql","r") as f:
    lines = f.readlines()
for table_name in ("advanced_searches", "test_table2", "test_table1"):
    lines = removelines(lines, table_name)
with open("backuptest.sql", "w") as f
    f.writelines(lines)