从.sql文件中“删除”一段行的问题
我正在写一个脚本,目的是从一个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_unicode_ci;”(也就是这一行的右括号及其后面的内容)。
谢谢任何帮助。我会继续努力找出我遗漏的部分。
2 个回答
0
最好不要用全局变量来代替函数的参数,因为使用参数可以让函数和它所在环境之间的关系更加清晰。既然你想从一个文件中删除几个表格,最好的方法是先把所有的行读进来,然后把需要的行作为新的结果返回。
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)
1
试试 sqlparse
$ pip install 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;']
这样就能得到正确解析的脚本,最后要做的就是逐个筛选,挑选出那些看起来需要的部分。这一步就留给你自己去完成。