使用Perl 6语法解析结构化文本时如何跳过不相关的行?
How to skip unrelated lines when using Perl 6 Grammar to parse structurized text?
我想使用 Perl 6 语法来描述一个 .sql
文件,我想知道我在解析时是否可以跳过一些不相关的行?
例如:我想跳过以下文本中的 DROP
行、/*!....!*/
行、--
行和 CREATE TABLE
块外的空白。
也就是说,我只想专注于 CREATE TABLE
个块:
DROP TABLE IF EXISTS `abcd`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `abcd` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'app_id',
`username` varchar(255) DEFAULT NULL COMMENT 'username',
`url` varbinary(255) DEFAULT NULL COMMENT 'url',
PRIMARY KEY (`id`),
UNIQUE KEY `NewIndex1` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=954 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `temp`
--
DROP TABLE IF EXISTS `temp`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `temp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`address` varchar(15) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`phone_model` varchar(10) NOT NULL,
`expire_time` varchar(15) NOT NULL,
`created` varchar(15) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1496 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
有什么建议吗?
扔掉操作 class.
中的值怎么样?
grammar SQL {
token TOP { <command>+ %% \n }
token command { <create-table> | <drop-table> | ... }
token drop-table { ... }
token create-table { ... }
...
}
class Create-only {
method TOP ($/) { make @<command>».made }
method command ($/) {
make $/.values[0].made
}
method drop-table ($/) { make Empty }
method create-table ($/) {
make %( $/.pairs.map: {.key => .value.made} )
# or whatever you need to to pass through the made values
}
...
}
SQL.parse($text,:actions(Create-only)).made;
显示它可以工作的快速示例:
grammar :: {
token TOP { <c>+ %% \n }
token c {<a>|<b>}
token a {a}
token b {b}
}.parse(
'abbbaab'.comb.join("\n"),
:actions(class :: {
method TOP ($/){make @<c>».made}
method a ($/){make ~$/}
method b ($/){make Empty}
method c($/){make $/.values[0].made }
})
).made.say
[a a a]
如果您使用 'rule' 而不是 'token',例如 Brad 的答案中的 SQL 语法,原子后的任何白色 space 都会变成 non-capturing调用<ws>
,这样你就可以重新定义<ws>
(whitespace)来包含其他你想忽略的东西,比如评论:
token ws { \s* | <slash-star-comment>* | <dashes-comment>* }
token slash-star-comment { \s* '/*!' .*? '!*/' \s* }
token dashes-comment { \s* '--' \N* \s* }
我把 \s* 分散在那里,这样你也可以在评论之前或之后有白色的 space。
我想使用 Perl 6 语法来描述一个 .sql
文件,我想知道我在解析时是否可以跳过一些不相关的行?
例如:我想跳过以下文本中的 DROP
行、/*!....!*/
行、--
行和 CREATE TABLE
块外的空白。
也就是说,我只想专注于 CREATE TABLE
个块:
DROP TABLE IF EXISTS `abcd`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `abcd` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'app_id',
`username` varchar(255) DEFAULT NULL COMMENT 'username',
`url` varbinary(255) DEFAULT NULL COMMENT 'url',
PRIMARY KEY (`id`),
UNIQUE KEY `NewIndex1` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=954 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `temp`
--
DROP TABLE IF EXISTS `temp`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `temp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`address` varchar(15) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`phone_model` varchar(10) NOT NULL,
`expire_time` varchar(15) NOT NULL,
`created` varchar(15) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1496 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
有什么建议吗?
扔掉操作 class.
中的值怎么样?grammar SQL {
token TOP { <command>+ %% \n }
token command { <create-table> | <drop-table> | ... }
token drop-table { ... }
token create-table { ... }
...
}
class Create-only {
method TOP ($/) { make @<command>».made }
method command ($/) {
make $/.values[0].made
}
method drop-table ($/) { make Empty }
method create-table ($/) {
make %( $/.pairs.map: {.key => .value.made} )
# or whatever you need to to pass through the made values
}
...
}
SQL.parse($text,:actions(Create-only)).made;
显示它可以工作的快速示例:
grammar :: {
token TOP { <c>+ %% \n }
token c {<a>|<b>}
token a {a}
token b {b}
}.parse(
'abbbaab'.comb.join("\n"),
:actions(class :: {
method TOP ($/){make @<c>».made}
method a ($/){make ~$/}
method b ($/){make Empty}
method c($/){make $/.values[0].made }
})
).made.say
[a a a]
如果您使用 'rule' 而不是 'token',例如 Brad 的答案中的 SQL 语法,原子后的任何白色 space 都会变成 non-capturing调用<ws>
,这样你就可以重新定义<ws>
(whitespace)来包含其他你想忽略的东西,比如评论:
token ws { \s* | <slash-star-comment>* | <dashes-comment>* }
token slash-star-comment { \s* '/*!' .*? '!*/' \s* }
token dashes-comment { \s* '--' \N* \s* }
我把 \s* 分散在那里,这样你也可以在评论之前或之后有白色的 space。