gpt4 book ai didi

regex - 使用 Perl 前瞻断言查找单个列表

转载 作者:行者123 更新时间:2023-12-05 02:34:49 25 4
gpt4 key购买 nike

给定一个这样的列表:

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;'

出现太短了:

direct_SQL_statement ::=
d
^^

directly_executable_statement ::=
d
^^

direct_SQL_data_statement ::=
d
^^

direct_implementation_defined_statement ::=
"
^^

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

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 定义,应该这样对待。 /* ... */ 注释应该从输出中过滤掉。
  • 评论周围可能没有空行。这就是我需要依赖前瞻断言而不是段落模式的原因。
  • 这个问题是对 How can EBNF or BNF be parsed? 的跟进,其解决方案是 “W3C EBNF 不会以分号结束产生式,因为::= 运算符出现在新产生式的 LHS 符号之后。”
  • 整个文件可以在 github.com/ronsavage/SQL/blob/master/sql-2016.ebnf 找到

最佳答案

带有可能需要省略的注释(/* ... */):

perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt

这会捕获包含 ::= 的一行及其后的所有内容:更多换行符,或 /*...*/ 注释,或结束符-字符串。

修饰符 /s 使 . 也匹配换行符,它通常不匹配,因此 .*? 可以匹配多行文本。使用 /x 文字空格将被忽略,可用于提高可读性。

或者,先删除注释,然后用多个换行符拆分输入字符串

perl -0777 -wnE's{ (?: /\* .*? \*/ ) }{\n}gsx; say for split /\n\n+/;' bnf.txt

我认为不需要前瞻。


这篇文章的原始版本使用了 paragraph mode ,通过 -00,或将整个输入拆分为多个换行符的正则表达式。

这非常简单和干净 -- 使用问题原始版本的输入,即没有评论。然后添加的评论可能有空行,并且段落中的阅读不再有效,因为会引入虚假的评论。

我正在下面恢复它,因为它被认为有用 --

如果总是有一个空行来分隔感兴趣的 block ,那么可以处理 in paragraphs

perl -00 -wne'print' file

这会保留空行,您似乎无论如何都想保留它。如果没有,可以将其删除。

(好奇的是,evan 可以简单地执行 perl -00 -pe'1' file)

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

perl -0777 -wnE'@chunks = split /\n\n+/; say for @chunks' file

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

perl -0777 -wnE'say for split /\n\n+/' file

block 之间的空行现在被删除了。

我看不出有什么理由进行前瞻。


我意识到“BNF 定义”可能是带有::= 的行之后。在那种情况下,一种方式

perl -0777 -wnE'say for /(.+?::=.*?)\n(?:\n+|\z)/gs' file

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

perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt


提醒:所有对帖子的修订都可以通过帖子正下方的链接查看,带有 last-edit timestamp 的文本.

关于regex - 使用 Perl 前瞻断言查找单个列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70702953/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com