【问题标题】:Replace for a pattern替换为模式
【发布时间】:2019-01-07 11:33:08
【问题描述】:

我尝试用.equals( 替换== 的模式。但是为了关闭括号 ) ,我面临一个问题,因为每次模式都可能不同。那么我应该考虑什么作为基本标准?

对于下面的代码,我编写的模式可以正常工作,但是当模式发生变化时,例如如果消息为:if ((var1 == null) || (var1.equals(""))) { var1 = "id";},那么我的代码就会失败。

message = '''if (var1 != null && var1 == "") var1 = null;'''

message = message.replace('==','.equals(')
result = re.sub('\&\&(.+?)\)', '\\1))', message)

我想要一个可以将== 修改为.equals() 而不会干扰变量和现有代码的模式。

【问题讨论】:

  • 这不是正则表达式适合的东西。确定== 的第二个操作数并不简单,它取决于您无法在正则表达式中表示的运算符优先级等因素。
  • @jonrsharpe :所以我们可能得不到一个简单的模式??
  • 与其说是 “可能不会”,不如说是 “如果可能的话,绝对不会”
  • @jonrsharpe 谢谢

标签: python regex python-2.7


【解决方案1】:

如果您正在寻找可以 100% 工作的东西,那么您需要一个语言解析器。

但是,如果我是正确的,您只是在尝试对大量代码进行查找/替换,那么大约 80% 的值是可以接受的(并且您可以修复任何问题),那么类似以下的内容应该适合您的需求:

([a-zA-Z]\w+|[)])(\s*==\s*("[^"]*"|\w+)(?=\s*[|;&)]))

您可以在替换字符串中使用组引用来获取组的内容,这将允许您保留匹配的内容。像这样:

$1.equals($3)

这将转换一些像这样的代码:

if ( foo == "bar" || foo == baz && foo == baz + 1 /*right hand side too complex*/ && bar == baz ){

  foo = baz( "bat" ) == bar;
  foo = bar == baz( "bat" ); // right hand side is too complex
  bar = 77 == 99; // left hand side is not a variable
  bar = bat == 99;
  bar = bat == 99.0; // floats not supported

}

进入这个:

if ( foo.equals("bar") || foo.equals(baz) && foo == baz + 1 /*right hand side too complex*/ && bar.equals(baz) ){

  foo = baz( "bat" ).equals(bar);
  foo = bar == baz( "bat" ); // right hand side is too complex
  bar = 77 == 99; // left hand side is not a variable
  bar = bat.equals(99);
  bar = bat == 99.0; // floats not supported

}

这是一个演示:https://regexr.com/461lm

请注意,这不会尝试在== 的右侧是表达式的情况下进行更复杂的替换,但它会处理简单的变量、字符串和整数。

【讨论】:

    【解决方案2】:

    好吧,现在我通过编写一个非常简单的函数来接近它,但我当然想看看你需要多长的代码来确保它正常工作。我对此进行的所有测试都有效。顺便说一句,我结合了“正则表达式”和“替换”,因为替换很棒

    输入

    >>> def replace_equals(message):
            import re
            found_equals = list(set(re.findall('[\s]+==[\S\s]*?\)', message)))
            for i in range(len(found_equals)):
                edit_found_equals = found_equals[i].replace(' == ', '.equals(').replace(')', '))')
                message = message.replace(found_equals[i], edit_found_equals)
            print(message)
    

    输出

    1.
    >>> message = '''if (var1 != null && var1 == "") var1 = null;'''
    >>> replace_equals(message)
    'if (var1 != null && var1.equals("")) var1 = null;'
    
    2.
    >>> message = '''if ((var1 == null) || (var1.equals(""))) { var1 = "id";}'''
    >>> replace_equals(message)
    'if ((var1.equals(null)) || (var1.equals(""))) { var1 = "id";}'
    

    基本解释

    我使用正则表达式 (re.findall) 来查找每次出现的“==[任意数量的字符并在您点击 ')'] 时终止并将它们放在一个列表中。我遍历该列表,编辑我发现的字符串,用“.equals(”和“)”替换“==”,然后在消息中搜索我找到的原始字符串并将其替换为我创建的那个字符串的新编辑。

    【讨论】:

    • 谢谢,是的,您的解决方案适用于这种特定模式,但不适用于通用模式。
    • 是的,我也这么认为。我看到另一个答案得到了您的认可,这很好。
    • 是的,这个答案让我想到了使用各种 if 子句解决 50% 问题的想法。
    猜你喜欢
    • 2016-07-17
    • 2012-12-25
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    相关资源
    最近更新 更多