【问题标题】:Removing/replacing multi-line code sections with python用python删除/替换多行代码部分
【发布时间】:2012-05-06 07:06:38
【问题描述】:

我正在尝试在 python 的帮助下从各种文件中删除包含过时代码片段的多行。我找了一些例子,但真的找不到我要找的东西。我基本上需要的是原则上执行以下操作(包含非python语法):

def cleanCode(filepath):
"""Clean out the obsolete or superflous 'bar()' code."""
with open(filepath, 'r') as foo_file:
    string = foo_file[index_of("bar("):]
    depth = 0
    for char in string:
        if char == "(": depth += 1
        if char == ")": depth -= 1
        if depth == 0: last_index = current_char_position
with open(filepath,'w') as foo_file:
    mo_file.write(string)

问题是我正在解析并想要替换的构造可能包含其他嵌套语句,这些语句也需要作为bar(...) 删除的一部分删除。

下面是要清理的示例代码 sn-p 的样子:

annotation (
  foo1(k=3),
  bar(
    x=0.29,
    y=0,
    bar1(
    x=3, y=4),
    width=0.71,
    height=0.85),
  foo2(System(...))

我认为以前可能有人解决过类似的问题:)

【问题讨论】:

  • 除非你有成千上万个这样复杂的表达式,否则手工操作可能更简单,也许有sed 的帮助。如果问题足够大,足以证明正确的解决方案,那么真正的正确解决方案就是构建 AST,对其进行修改,然后将其转换回代码。万无一失,简单,大部分已经在 stdlib 中完成,但需要理解并且当您需要输出的异国编码风格时可能需要额外的工作。
  • 您正在处理的代码是否也是 Python 代码?如果不是,那是什么?
  • 我建议你描述你想要做什么,而不是仅仅跳到你是如何尝试去做的。这似乎有时您会在编辑器/IDE 中使用正则表达式替换或使用重构工具。
  • 您的代码片段将文件的内容读入字符串,运行一个不修改字符串的循环,然后将未修改的字符串写回同一个文件。我错过了什么吗?
  • @delnan:你如何找到一个用 sed 括号括起来的字符串?

标签: python


【解决方案1】:

Pyparsing 有一些用于匹配嵌套括号文本的内置插件 - 在您的情况下,您并没有真正尝试提取括号的内容,您只需要最外面的 '(' 和 ')' 之间的文本。

from pyparsing import White, Keyword, nestedExpr, lineEnd, Suppress

insource = """
annotation (
  foo1(k=3),
  bar(
    x=0.29,
    y=0,
    bar1(
    x=3, y=4),
    width=0.71,
    height=0.85),
  foo2(System(...))
"""

barRef = White(' \t') + Keyword('bar') + nestedExpr() + ',' + lineEnd

out = Suppress(barRef).transformString(insource)
print out

打印

annotation (
  foo1(k=3),
  foo2(System(...))

编辑:解析操作以不剥离以 '85' 结尾的 bar() 调用:

barRef = White(' \t') + Keyword('bar') + nestedExpr()('barargs') + ','
def skipEndingIn85(tokens):
    if tokens.barargs[0][-1].endswith('85'):
        raise ParseException('ends with 85, skipping...')
barRef.setParseAction(skipEndingIn85)

【讨论】:

  • 感谢 Paul,这正是我想要的。我想知道是否也可以提供一组关键字。例如,如果我想匹配 'bar()' 和/或 'foo2()'。
  • Paul 再向你的好图书馆提出一个问题,我尝试扩展 nestedExpr 以处理一些特殊情况,但由于某种原因,nestedExpr('(','85)') 与上面的“bar”示例不匹配。这里是我使用的整个 barRef:barRef = ZeroOrMore(White(' \t')) + Keyword('bar') + nestedExpr('(','85)') + ',' + ZeroOrMore(White(' \t') + lineEnd )
  • nestedExpr 中的结束字符串应该是 every 嵌套括号的结束字符串,而不仅仅是最后一个,并且嵌入的括号以 '4)' 结尾,而不是'85)'。至于匹配各种关键字,只需将Keyword('bar')改为(Keyword('bar')|Keyword('baz')|Keyword('foo2'))即可。
  • 啊,我明白了。那么,如何将删除限制为仅以“85)'”结尾的那些“条形”结构?
  • 向 nestedExpr 添加一个解析操作,查看最后一个最外层标记(可能是标记[0][-1]),以查看它是否为 85,如果它没有引发 ParseException。 if tokens[0][-1] != '85': raise ParseException('must end in 85')。查看文档以了解如何添加解析操作。
【解决方案2】:

试试这个:

clo=0
def remov(bar):
   global clo
   open_tag=strs.find('(',bar) # search for a '(' open tag
   close_tag=strs.find(')',bar)# search for a ')' close tag
   if open_tag > close_tag:
      clo=strs.find(')',close_tag+1)
   elif open_tag < close_tag and open_tag!=-1:
      remov(close_tag)



f=open('small.in')
strs="".join(f.readlines())
bar=strs.find('bar(')
remov(bar+4)
new_strs=strs[0:bar]+strs[clo+2:]
print(new_strs)
f.close()   

输出:

annotation (
  foo1(k=3),
  foo2(System(...))

【讨论】:

  • 感谢 Aswini,如果没有更舒适的 pyparsing,这将完成这项工作 :)
猜你喜欢
  • 1970-01-01
  • 2021-05-19
  • 2019-06-08
  • 1970-01-01
  • 2017-10-24
  • 2011-07-01
  • 1970-01-01
  • 2019-04-15
  • 2013-06-07
相关资源
最近更新 更多