DROP TABLE IF EXISTS `qalnk`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `qalnk` (
`id` bigint(20) NOT NULL,
`answer_id` bigint(20) DEFAULT NULL,
`date_deleted` bigint(20) DEFAULT NULL,
`deleted_by_user_ap_id` varchar(36) DEFAULT NULL,
`expression_id` bigint(20) DEFAULT NULL,
`expression_type` varchar(255) DEFAULT NULL,
`ordering` int(11) DEFAULT NULL,
`question_id` bigint(20) DEFAULT NULL,
`expression_for_deselect_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK6661B19F393DFCD` (`expression_id`),
KEY `FK6661B195182DDCD` (`question_id`),
KEY `FK6661B195742A56B` (`expression_for_deselect_id`),
KEY `idx_qlnk_nswrd` (`answer_id`),
KEY `FK6661B19126D878D` (`answer_id`),
KEY `FK6661B1975B33071` (`id`),
CONSTRAINT `FK6661B19126D878D` FOREIGN KEY (`answer_id`) REFERENCES `ans` (`id`),
CONSTRAINT `FK6661B1975B33071` FOREIGN KEY (`id`) REFERENCES `apobj` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
我的目标是从数据库中删除所有约束,因此我希望对单词" CONSTRAINT"进行简单的代码搜索。并删除该行
我尝试使用sed
sed '/\s*CONSTRAINT/d' ~/Downloads/dump.sql > ~/ouput.sql
但由于CONSTRAINTS是最后一个声明,所有这些尾部逗号都被遗忘了。我不介意它是awk,sed还是一些常用工具。
所需的输出是
DROP TABLE IF EXISTS `qalnk`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `qalnk` (
`id` bigint(20) NOT NULL,
`answer_id` bigint(20) DEFAULT NULL,
`date_deleted` bigint(20) DEFAULT NULL,
`deleted_by_user_ap_id` varchar(36) DEFAULT NULL,
`expression_id` bigint(20) DEFAULT NULL,
`expression_type` varchar(255) DEFAULT NULL,
`ordering` int(11) DEFAULT NULL,
`question_id` bigint(20) DEFAULT NULL,
`expression_for_deselect_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK6661B19F393DFCD` (`expression_id`),
KEY `FK6661B195182DDCD` (`question_id`),
KEY `FK6661B195742A56B` (`expression_for_deselect_id`),
KEY `idx_qlnk_nswrd` (`answer_id`),
KEY `FK6661B19126D878D` (`answer_id`),
KEY `FK6661B1975B33071` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
答案 0 :(得分:2)
sed是一个很好的工具,可以在一行上进行简单的替换,但对于其他任何东西只需使用awk。这是多字符RS的GNU awk和\s
的{{1}}缩写:
[[:space:]]
对于仅限POSIX的解决方案(请参阅以下来自@ mklement0的评论):
$ awk -v RS='^$' -v ORS= '{gsub(/,\s*CONSTRAINT[^\n,]+/,"")}1' file
DROP TABLE IF EXISTS `qalnk`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `qalnk` (
`id` bigint(20) NOT NULL,
`answer_id` bigint(20) DEFAULT NULL,
`date_deleted` bigint(20) DEFAULT NULL,
`deleted_by_user_ap_id` varchar(36) DEFAULT NULL,
`expression_id` bigint(20) DEFAULT NULL,
`expression_type` varchar(255) DEFAULT NULL,
`ordering` int(11) DEFAULT NULL,
`question_id` bigint(20) DEFAULT NULL,
`expression_for_deselect_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK6661B19F393DFCD` (`expression_id`),
KEY `FK6661B195182DDCD` (`question_id`),
KEY `FK6661B195742A56B` (`expression_for_deselect_id`),
KEY `idx_qlnk_nswrd` (`answer_id`),
KEY `FK6661B19126D878D` (`answer_id`),
KEY `FK6661B1975B33071` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
答案 1 :(得分:0)
它有点像黑客 - 使用(GNU)awk
将尾随,
转移到后续行的开头,然后是sed
删除。
awk -v RS= '{gsub(/,\n/, "\n,"); print}' ~/Downloads/dump.sql |
sed '/\s*CONSTRAINT/d' > ~/ouput.sql
这给了我以下内容,它应该是有效的SQL
DROP TABLE IF EXISTS `qalnk`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `qalnk` (
`id` bigint(20) NOT NULL
, `answer_id` bigint(20) DEFAULT NULL
, `date_deleted` bigint(20) DEFAULT NULL
, `deleted_by_user_ap_id` varchar(36) DEFAULT NULL
, `expression_id` bigint(20) DEFAULT NULL
, `expression_type` varchar(255) DEFAULT NULL
, `ordering` int(11) DEFAULT NULL
, `question_id` bigint(20) DEFAULT NULL
, `expression_for_deselect_id` bigint(20) DEFAULT NULL
, PRIMARY KEY (`id`)
, KEY `FK6661B19F393DFCD` (`expression_id`)
, KEY `FK6661B195182DDCD` (`question_id`)
, KEY `FK6661B195742A56B` (`expression_for_deselect_id`)
, KEY `idx_qlnk_nswrd` (`answer_id`)
, KEY `FK6661B19126D878D` (`answer_id`)
, KEY `FK6661B1975B33071` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
答案 2 :(得分:-1)
搜索具有表达式" CONSTRAINT"的任何行。并在该行之前删除行和,
。
sed -e '/.*/{
N
s/,\n.*CONSTRAINT//g}' -e '/.*CONSTRAINT.*/d' my_file
答案 3 :(得分:-2)
尽管票数下降,我认为这个答案提供了有效的解决方案,可以像宣传的那样工作,同时(希望)也能提供信息。请告诉我们,如果不是,我可以解决它。
单次 sed
解决方案要求所有输入行一次读取,类似于Ed Morton's helpful awk
answer:
GNU sed
解决方案:
sed -zr 's/,\n\s*CONSTRAINT\s+[^\n,]+//g' file
-z
使用NUL(空字节)作为输入行分隔符,并且由于输入中没有嵌入的NUL,因此file
的整个内容被读入模式空间中一次。
-r
启用扩展正则表达式(现代语法,扩展功能)。
正则表达式删除所有CONSTRAINT
行,包括前一行的,\n
,这使得封闭的CREATE TABLE
语句的语法保持不变。
遗憾的是, BSD (macOS)sed
解决方案更加繁琐:
BSD sed
版本缺少许多GNU(非标准)便利功能,这使得解决方案更加痛苦。
BSD sed
仅为POSIX标准提供了一些扩展,但值得注意的是能够使用所谓的扩展正则表达式。
sed -E ':a
$!{N;ba
}
s/,\n([[:blank:]]*CONSTRAINT[[:blank:]]+[[:print:][:blank:]]+\n)+/\
/g' file
-E
- 类似于GNU sed
' s -r
- 启用扩展正则表达式。
:a\n$!{N;b\na}
是一种常见的sed
成语,可以立即读取整个输入:
:a
定义了要跳转到的标签。$!
匹配的每一行,但(!
)最后一行($
){N;ba};
读取模式空间中的下一行(要操作的输入缓冲区),然后将(b
)分支到标签a
(:a
)。s
)。请注意所需的换行符,以终止分支标签和分支命令,以及(以转义形式)替换命令。
-e
选项将其填充到一行中,但这会使命令的可读性降低。[[:blank:]]
,因为不支持\s
等快捷类。
\n
原则上可以在正则表达式中匹配,但在字符类中无法识别 >。因此,[^\n]
必须使用[[:print:][:blank:]]
进行模拟 - 添加[:blank:]
以匹配标签字符,这些字符不会被视为可打印字符; (\t
不能在char。类中使用。)