如何在使用 transformString 后有效地检查定义的语法是否被替换?

How to efficiently check if defined grammar was replaced after using transformString?

我编写了一个 python 脚本来从数千个 SQL 文件中去除 RCS 关键字。基本上它使用 pyparse transformString 来转换和剥离已知的 RCS 标签。然而这个函数是有效的,因为我无法知道 transformString 是否执行了 ParseAction,我的脚本只是盲目地重写 sql 代码文件,即使扫描文件中没有 RCS 关键字。

这是我的示例代码,我在其中删除了 RCS 关键字,在我决定写入当前文件之前,我需要知道该操作是否找到了要替换的标记并实际执行了替换。如果没有由 transformString 完成的替换,我想跳过写入文件。

from pyparsing import *
# simulate some SQL code
original_code = """
CREATE OR REPLACE FUNCTION oracle_function_name
 (
 p_company_code IN varchar2

)
--
RETURN number
IS

-- $Workfile: oracle_function_name.sql $
-- $Author: az $
-- $Date: 2018/11/20 $
-- $Revision: #1 $

l_rate := 0;
end if;
Close cur_rate;
--
return l_rate;
end;
/

"""
# Grammar definitions
Workfile_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Workfile:') + Word( alphas+"_"+alphas+".", alphanums+"_"+alphas+".") + CaselessKeyword('$') + LineStart()
Workfile_Grammar.setParseAction( replaceWith("") )

author_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Author:') + Word( alphas+"_"+alphas+".", alphanums+"_"+alphas+".") + CaselessKeyword('$')  + LineStart()
author_Grammar.setParseAction(replaceWith(""))

date_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Date:') + Word( alphanums+"/"+alphanums+"/") + CaselessKeyword('$')  + LineStart()
date_Grammar.setParseAction(replaceWith(""))

revision_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Revision:') + Word( '#'+alphanums) + CaselessKeyword('$')  + LineStart()
revision_Grammar.setParseAction(replaceWith(""))

change_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Change:') + Word(alphanums) + CaselessKeyword('$')  + LineStart()
change_Grammar.setParseAction(replaceWith(""))

dateTime_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Date:') + Word( alphanums+"/"+alphanums+"/") + Word(alphanums+":"+alphanums+":"+alphanums) + CaselessKeyword('$')  + LineStart()
dateTime_Grammar.setParseAction(replaceWith(""))

header_Grammar = ZeroOrMore('/*') + ZeroOrMore('*') + ZeroOrMore('--')+ CaselessKeyword('$Header:') + Word( "//"+alphanums+"/"+alphas+"_"+alphas+".", alphanums+"_"+alphas+".") + CaselessKeyword('$')  + LineStart()
header_Grammar.setParseAction( replaceWith("") )

postStripFile = author_Grammar.transformString(header_Grammar.transformString(dateTime_Grammar.transformString(change_Grammar.transformString(revision_Grammar.transformString(date_Grammar.transformString(Workfile_Grammar.transformString(original_code)))))))
# Is there a way to check the transFormStrings have found and removed any Grammar (RCS keywords?)

print(postStripFile)

# this is where we write postStripFile back to the original file name 
# so that the files with RCS tags are stripped in place and the ones without are left in place without changes.

最简单的方法是比较调用 transformString 前后的字符串,如果不同,则写入文件。

# combine all transformers into a single parser, so transform can be done in
# one pass
parser = (Workfile_Grammar
          | date_grammar
          | revision_grammar
          | change_grammar
          | dateTime_grammar
          | header_grammar
          | author_grammar
         )

new_sql = parser.transformString(original_sql)
if new_sql != original_sql:
    # do whatever when detecting original has been transformed

稍微更有效的方法可能是向所有将全局变量设置为 True 的表达式添加另一个解析操作:

changed = False
def changes_made():
    global changed
    changed = True

Workfile_Grammar.setParseAction(changes_made, replaceWith(""))
...

changed = False
new_sql = parser.transformString(original_sql)
if changed:
    # ... etc. ...

setParseAction 将接受在成功解析后调用的多个函数。由于 changes_made 不对解析的标记进行任何修改,因此就 pyparsing 而言,它只是一个传递。

在同一 运行.

中多次调用 transformString 之前,您必须确保将 changes_made 重置为 False

我个人的偏好是更简单的第一种方法。