我有一个Oracle SQL脚本,其中包含多个语句,这些语句由“;“。我正在尝试删除整个脚本中的所有注解。这包括:
1.单行注解--
直到换行。
1.阻止注解/*... */
1.此外,我希望能够将整个脚本分割成语句。
我知道一个名为sqlparse
的库可以格式化以删除代码,但我遇到了这个边缘情况:
edge_case = """myval := oneval || otherval ||--;
-- single comment line
lpad(nvl(myval, ' '), 10, ' ');
"""
formatted = sqlparse.format(edge_case, strip_comments=True)
sqlparse.split(formatted)
# returns ['myval := oneval || otherval ||--;', "lpad(nvl(myval, ' '), 10, ' ');"]
# it splits into 2 statements when it should only be 1!
我的想法是专注于每一个注解情况,然后尝试只通过由sql中所有有效字符组成的字符串标记来解析其余的非注解代码。
from pyparsing import *
# define basic elements
semicolon = Literal(";")
# all valid chars excluding semicolon
all_valid_chars = alphanums + "_-+*/.,:()[]{}<>=&|"
# define an sql token
sql_token = Word(all_valid_chars)
# need to make sure that "--" is a special case
single_line_comment_token = Literal("--")
single_line_comment = single_line_comment_token + SkipTo(line_end) + line_end
test1_single_line_comment = """
-- single comment line
--- also a comment
---- also a comment
-- comment -- continues
-- comment /* also continues */
# - not a comment
"""
single_line_comment.run_tests(test1_single_line_comment)
# also handle multi line comments
multi_line_comment_open = Literal("/*")
multi_line_comment_close = Literal("*/")
multi_line_comment = multi_line_comment_open + SkipTo(multi_line_comment_close) + multi_line_comment_close
test1_multi_line_comment = """
/* multi line comment */
/* outer comment /* inner comment */
/* /* /* still valid */
/* -- still valid */
"""
multi_line_comment.run_tests(test1_multi_line_comment)
test2_multi_line_comment = """
/* multi line comment /* with nested comment should fail! */ */
"""
multi_line_comment.run_tests(test2_multi_line_comment, failure_tests=True)
我现在被困在这里,不知道在哪里继续。
statement2 = OneOrMore(single_line_comment | multi_line_comment | sql_token) + semicolon
# run tests
print(statement2.parseString("myval := oneval || otherval ||--;"))
我的问题:
1.这些情况下的每一个测试工作,但我不知道我应该如何测试在一起,以涵盖重叠,如。-- /*
这应该是一个单行注解等。
1.我不知道如何正确处理其余的非注解代码。例如,所有有效字符都应该包括-
,但这会打乱我的单行代码吗?面临的技术问题较少:
1.老实说,我不知道从哪里开始,也不知道如何构建我的代码,因为这些情况可能会重叠。我甚至不确定pyparsing是否是我应该做的来解决这个问题,但是根据我看到的试图从sql中删除注解的问题,解析是唯一真实的可靠的解决方案。
run_tests
不能处理多行。这使得很难测试块注解,尽管我可以使用parse_string
。
1条答案
按热度按时间h4cxqtbf1#
对于剥离注解(或任何pyparsing表达式),您应该使用
transform_string
,而不是parse_string
。transform_string
扫描输入字符串并应用解析操作和抑制。下面是一些从脚本中剥离python注解的代码:给出:
糟糕,这并没有检测到
#hello
在一个带引号的字符串中。为了解决这个问题,我们还插入了一个带引号的字符串解析器,但是这些字符串不会被抑制:
现在给出:
对于SQL注解处理,您将执行大致相同的操作:
打印:
我很高兴看到你正在使用run_tests!如果要定义跨多行的测试,而不是使用多行字符串形式,请将测试作为字符串列表传递:
不幸的是,我没有调用transform_string的run_tests版本。
最好在第一次剥离注解之后,在第二次传递中将行拆分为单独的语句。您可以尝试以下操作:
然后使用与剥离注解相同的转换模式(但这一次使用的是解析操作而不是抑制)。或使用scan_string定位“;“终止符,然后将位于分号之间的SQL写出到它们各自的文件中(留给读者作为练习)。