考虑以下文本(顺便说一下,它是 MySQL 转储的一部分):
创建表`表`( `id` int(10) NOT NULL 自动增量, `name` varchar(100) NOT NULL default '', `description` 文本不为空, 主键 (`id`), 全文键 `full_index` (`name`) )引擎=MyISAM 默认字符集=latin1; /*!40101 设置 character_set_client = @saved_cs_client */;
我想删除该FULLTEXT
键,并且还想删除上面一行末尾的逗号,以便 SQL 仍然有效。
有人能想出(并解释)一个sed
方法来做到这一点吗?
答案1
AWK 答案
将示例文本放在名为 的文件中sql
,其模式如下(为了清楚起见,带有换行符和缩进):
awk -v skip=1 '{
if (skip) { skip=0 }
else {
if (/FULLTEXT KEY/) { skip=1; sub(/,$/, "", prevline) }
print prevline
}
prevline=$0
}
END { print prevline }' sql
生成:
CREATE TABLE `table` (
`id` int(10) NOT NULL auto_increment,
`name` varchar(100) NOT NULL default '',
`description` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
解释:
- 我们通过只打印之前在每次迭代中检查当前行之后,遇到的行。
- 如果当前行包含
FULLTEXT KEY
标记,我们会设置一个标志以在下一次迭代中跳过打印此行。我们还会删除即将打印的上一行的尾随逗号。 - 我们通过最初设置为(“true”)来跳过打印空的初始行(之前
prevline
已经设置) 。skip
1
- 我们通过在脚本末尾添加额外的打印来确保打印最后一行
prevline
。请注意,当前实现假设最后一行不是有被跳过风险的行,即它不包含标记FULLTEXT KEY
。
原始(不完整)sed
答案
这个答案是不完整的,并且在大多数情况下肯定是不正确的,因为sed
在进行多行匹配时,输入流会消耗得太快而无法达到预期的结果——正如评论中指出的那样,它只适用于偶数行的匹配!sed
没有“真正的”前瞻功能,所以我们最好使用 Python/Perl/etc.,或者如上所述的 AWK。
将示例文本放在名为 的文件中sql
,其模式如下:
$ sed 'N; s/,\n FULLTEXT.*//' sql
生成:
CREATE TABLE `table` (
`id` int(10) NOT NULL auto_increment,
`name` varchar(100) NOT NULL default '',
`description` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
解释:
N
启用多行匹配。\n
表示换行。s/pattern/replacement/
是标准替换语法。.*
将匹配当前行末尾的任何内容。
答案2
使用 sed 管理两行并不困难。
只需在模式空间中保留两行即可。
- $!N :此命令在模式空间中附加一行。
- P :打印模式空间中的第一行
- D :删除模式空间中的第一行并开始新循环(不读取一行)
如果只剩下一行则其行为类似于“d”命令(即读取一行并开始新循环)
sed -n '$!N; s/,[[:space:]]*FULLTEXT KEY.*// ;P;D'