首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Perl前瞻性断言查找单个列表。

使用Perl前瞻性断言查找单个列表。
EN

Stack Overflow用户
提问于 2022-01-13 20:49:43
回答 1查看 104关注 0票数 3

给出了这样的清单:

代码语言:javascript
复制
direct_SQL_statement ::=
  directly_executable_statement semicolon

directly_executable_statement ::=
    direct_SQL_data_statement
  | SQL_schema_statement
  | SQL_transaction_statement
  | SQL_connection_statement
  | SQL_session_statement
  | direct_implementation_defined_statement

direct_SQL_data_statement ::=
    delete_statement__searched
  | direct_select_statement__multiple_rows
  | insert_statement
  | update_statement__searched
  | truncate_table_statement
  | merge_statement
  | temporary_table_declaration

direct_implementation_defined_statement ::=
  "!! See the Syntax Rules."

apostrophe ::=
  "'"
/*
5.2     token and separator

Function

Specify lexical units (tokens and separators) that participate in SQL language.


Format
*/
token ::=
    nondelimiter_token
  | delimiter_token

identifier_part ::=
    identifier_start
  | identifier_extend
/*
identifier_start ::=
  "!! See the Syntax Rules."
identifier_extend ::=
  "!! See the Syntax Rules."
*/
large_object_length_token ::=
  digit+ multiplier

是否可以使用Perl的前瞻性断言将其分解为单独的定义列表?

我试过了

perl -0777ne 'print "$&\n^^\n\n" while /(?=\w+\s*::=)\w+\s*::=\s*.+/gs;'

但是它只是返回了整个东西(就好像前瞻性断言根本不起作用一样)。

perl -0777ne 'print "$&\n^^\n\n" while /(?=\w+\s*::=)\w+\s*::=\s*.+?/gs;'

出现得太短了:

代码语言:javascript
复制
direct_SQL_statement ::=
  d
^^

directly_executable_statement ::=
    d
^^

direct_SQL_data_statement ::=
    d
^^

direct_implementation_defined_statement ::=
  "
^^

我需要将其分解为单独的BNF定义块,以便进一步处理,如对初始测试数据的处理:

代码语言:javascript
复制
direct_SQL_statement ::=
  directly_executable_statement semicolon
^^


directly_executable_statement ::=
    direct_SQL_data_statement
  | SQL_schema_statement
  | SQL_transaction_statement
  | SQL_connection_statement
  | SQL_session_statement
  | direct_implementation_defined_statement
^^


direct_SQL_data_statement ::=
    delete_statement__searched
  | direct_select_statement__multiple_rows
  | insert_statement
  | update_statement__searched
  | truncate_table_statement
  | merge_statement
  | temporary_table_declaration
^^


direct_implementation_defined_statement ::=
  "!! See the Syntax Rules."
^^

笔记,

  • 上面的输出来自最初的测试数据。
  • 整个A ::= B被称为BNF定义。"^^“仅用于直观地指示分离是否正确。
  • apostrophe和下面的token是不同的BNF定义,应该这样处理。应该从输出中筛选出/* ... */注释。
  • 评论可能没有空行围绕在他们周围。这就是我需要依赖前瞻性断言而不是段落模式的原因。
  • 这个问题是如何解析EBNF或BNF?的后续问题,解决方案是"W3C EBNF不会以分号结束生产,因为::=操作符在新产品的LHS符号之后出现。“
  • 整个文件可以在github.com/ronsavage/SQL/blob/master/sql-2016.ebnf上找到
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-13 21:16:42

加上需要省略的可能的注释(/* ... */):

代码语言:javascript
复制
perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt

这捕获了一条带有::=的行及其后面的所有内容:更多的换行符,或者/*...*/注释,或者字符串的结尾。

修饰符/s也使.匹配换行符,这是它通常不匹配的,这样.*?就可以匹配多行文本。对于/x,文字空间被忽略,可以用于可读性。

或者,首先删除注释,然后将输入字符串拆分为多个新行。

代码语言:javascript
复制
perl -0777 -wnE's{ (?: /\* .*? \*/ ) }{\n}gsx; say for split /\n\n+/;' bnf.txt

我看不出有什么需要。

这篇文章的原始版本使用了一个https://perldoc.perl.org/perlrun#-0%5Boctal/hexadecimal%5D (通过-00__ ),或者一个正则表达式,它将整个输入分成多个换行符。

这是非常简单和干净的--用问题的原始版本,也就是没有评论的输入。然后添加的注释可能有空行,段落中的阅读不再流行,因为虚假的评论会被引入。

我正在恢复它,因为它被认为是有用的--

如果总是有一个空行分隔兴趣块,那么可以处理在段落中

代码语言:javascript
复制
perl -00 -wne'print' file

这保留了空行,您似乎无论如何都要保留它。如果没有,它可以被移除。

(奇怪的是,埃文可以做简单的perl -00 -pe'1' file)

否则,可以在多个换行符上断开该字符串。

代码语言:javascript
复制
perl -0777 -wnE'@chunks = split /\n\n+/; say for @chunks' file

或者,如果您确实需要输出它们

代码语言:javascript
复制
perl -0777 -wnE'say for split /\n\n+/' file

块之间的空行现在被移除。

我看不出有什么理由向前看。

我意识到"BNF定义“可能是::=后面的行。在这种情况下,有一种方法

代码语言:javascript
复制
perl -0777 -wnE'say for /(.+?::=.*?)\n(?:\n+|\z)/gs' file

但是,对于需要省略的可能的注释(/* ... */):

代码语言:javascript
复制
perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt

提示:所有对帖子的修改都可以通过链接看到,链接就在帖子下面,还有https://stackoverflow.com/posts/70703201/revisions的文本。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70702953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档