大文件上的多行正则表达式匹配字符串替换

multiline regex match string replacement on large file

我有一个很大的 mysqldump(4+ 演出),我们有一个存档类型 table,suffers from this bug 最终结果是我需要将 AUTO_INCREMENT 计数器重置为零.确实设法进行了替换,但它很丑陋,涉及将文件拆分成更小的块,然后 grepping 找到 table,查看我想要更改的数字,然后在 sed 上使用原始文件仅替换自动增量上的匹配项。就像我说的,太可怕了,但它奏效了。

所以 - 我已经尝试破译多行 sed,但没有做到那么远。我想做的是寻找我感兴趣的 table 名称,然后从那里找到下一个 AUTO_INCREMENT= ,然后匹配其中的数字,并将其设为零。这是 table:(假设在此点之前和之后有大量数据)

DROP TABLE IF EXISTS `archive_exported_problems`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `archive_exported_problems` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `export_id` int(11) DEFAULT NULL,
  `problem_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=ARCHIVE AUTO_INCREMENT=478 DEFAULT CHARSET=latin1;

我想做的是(自动)扫描文件直到它匹配

(?:CREATE TABLE `archive_exported_problems).*?AUTO_INCREMENT=(\d+)

(似乎有效的正则表达式)然后用 0

替换捕获组

我认为这是可能的 - 非常感谢任何帮助!

考虑一下:

$ sed -r '/CREATE TABLE `archive_exported_problems`/,/AUTO_INCREMENT=/ {s/(AUTO_INCREMENT)=[[:digit:]]+/=0/;}' file
DROP TABLE IF EXISTS `archive_exported_problems`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `archive_exported_problems` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `export_id` int(11) DEFAULT NULL,
  `problem_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=ARCHIVE AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;

对于Mac OSX (BSD),尝试:

$ sed -E -e '/CREATE TABLE `archive_exported_problems`/,/AUTO_INCREMENT=/ {s/(AUTO_INCREMENT)=[[:digit:]]+/=0/;}' file

工作原理

  • /CREATE TABLEarchive_exported_problems/, /AUTO_INCREMENT=/

    这将后续命令的范围限制在以包含 CREATE TABLE 'archive_exported_problems' 的行开始并以包含 AUTO_INCREMENT=.

  • 的行结束的行上
  • s/(AUTO_INCREMENT)=[[:digit:]]+/=0/

    这会执行您想要的替换。

限制

此方法假设 CREATE TABLE 短语和 AUTO_INCREMENT= 短语永远不会在同一行。如果那不是真的,我们需要做一些小的改变。

如果 perl 是一个选项,那么在 perl 中使用 DOTALL 标志会更容易,如下所示:

perl -00 -pe 
 's/(?s)(CREATE TABLE `archive_exported_problems`.*?AUTO_INCREMENT)=\d+/=0/' file.sql

DROP TABLE IF EXISTS `archive_exported_problems`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `archive_exported_problems` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `export_id` int(11) DEFAULT NULL,
      `problem_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
) ENGINE=ARCHIVE AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;

使用的选项是:

-00    # slurps whole file
(?s)   # enable DOTALL flag for regex