使用 Perl 前瞻断言查找单个列表
Using Perl look-ahead assertion to find individual list
给出这样的列表:
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 定义块以进一步处理,就像这样对于初始测试数据:
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
我认为不需要前瞻。
此 post 的原始版本使用了 paragraph mode,通过 -00
,或将整个输入拆分为多个换行符的正则表达式。
这非常简单明了 -- 使用问题原始版本的输入,即没有评论。然后添加的评论可能有空行,并且段落中的阅读不再有效,因为会引入虚假的评论。
我正在下面恢复它,因为它被认为有用 --
如果始终有空行分隔感兴趣的块,则可以处理 in paragraphs
perl -00 -wne'print' file
这会保留空行,您似乎无论如何都想保留它。如果没有,可以去掉。
(然后好奇埃文可以简单地做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
块之间的空行现已删除。
我看不出有什么理由要提前看一下。
我意识到“BNF 定义”可能是行在 之后::=
。在那种情况下,一种方式
perl -0777 -wnE'say for /(.+?::=.*?)\n(?:\n+|\z)/gs' file
但是,需要省略可能的注释 (/* ... */
):
perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt
提醒:所有对 post 的修订都可以通过 post 正下方的 link 查看,以及 [=] 的文本30=].
给出这样的列表:
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 定义块以进一步处理,就像这样对于初始测试数据:
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
我认为不需要前瞻。
此 post 的原始版本使用了 paragraph mode,通过 -00
,或将整个输入拆分为多个换行符的正则表达式。
这非常简单明了 -- 使用问题原始版本的输入,即没有评论。然后添加的评论可能有空行,并且段落中的阅读不再有效,因为会引入虚假的评论。
我正在下面恢复它,因为它被认为有用 --
如果始终有空行分隔感兴趣的块,则可以处理 in paragraphs
perl -00 -wne'print' file
这会保留空行,您似乎无论如何都想保留它。如果没有,可以去掉。
(然后好奇埃文可以简单地做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
块之间的空行现已删除。
我看不出有什么理由要提前看一下。
我意识到“BNF 定义”可能是行在 之后::=
。在那种情况下,一种方式
perl -0777 -wnE'say for /(.+?::=.*?)\n(?:\n+|\z)/gs' file
但是,需要省略可能的注释 (/* ... */
):
perl -0777 -wnE'say for m{(.*?::=.*?)\n (?: \n+ | (?:/\*.*?\*/) | \z)}gsx' bnf.txt
提醒:所有对 post 的修订都可以通过 post 正下方的 link 查看,以及 [=] 的文本30=].