【问题标题】:Replace java function using regex: matching nested brackets使用正则表达式替换java函数:匹配嵌套括号
【发布时间】:2013-04-11 04:51:14
【问题描述】:

我想用正则表达式替换函数定义和声明,即,

替换

public abstract void myFuction(MyParam myParam);

@Override
public void myFuction(MyParam myParam){

}

我试过这个正则表达式:

(@Override[\n\s\t]*)?public *(abstract)? *void
*generateProcessMethod *\(UIGenerationContext *[^)]+\)[\n\\s\t]*((\{[^{}]*?\})|;)

但问题是,如果该函数有任何其他{},那么它将不起作用。

[^{}] 替换为. 不是解决方案,因为它还替换了以下函数。

【问题讨论】:

  • JavaCC 和 ANTLR 等语法识别工具可能适合您的任务
  • 如果你有 intellij idea 的终极版本,他们有非常强大的结构搜索和替换工具,可以完全满足你的需求。
  • 你也可以看看 Eclipse JDT API。

标签: java regex


【解决方案1】:

使用正则表达式,这(括号嵌套)确实可以完成,但只能达到固定的嵌套级别。

你当前的正则表达式(改变了一点):

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*((\{[^\{\}]*?\})|;)

只允许一个级别。更具体地说,这是与之匹配的部分:

(\{[^\{\}]*?\})

如果您想匹配最多两个级别,请将提到的部分更改为:

(\{([^{}]*|\{[^{}]*\})*\})

因此:

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*(\{([^{}]*|\{[^{}]*\})*\}|;)

要添加更多关卡,您必须不断进行编辑。当您添加关卡时,它变得越来越混乱。

说明:

  • \{ 将匹配第一个左括号
    • (开群
      • [^{}]* 匹配括号以外的任何内容
      • |
      • \{ 如果它确实找到了一个左括号...
        • [^{}]* ...它将匹配除括号之外的任何内容...
      • \} ...直到找到右括号
    • ) 关闭群
    • *上述组可以发生零次或多次
  • \} 匹配结束括号

要添加更多关卡,请将中间(第二个)[^{}]* 部分更改为 ([^{}]*|\{[^{}]*\})*

如果您无法预测最大嵌套级别:

有些语言允许嵌套运算符R,它允许您嵌套任意数量的级别。如果您的语言不支持它(Java 不支持,afaik PHP 和 Perl 支持),您将不得不:

  • 预测最大嵌套级别;或
  • 自己创建解析器。

正则表达式,没有R 运算符,不能嵌套任意数量的级别。

也就是说,使用R 运算符是这样的:

(\{([^{}]|(?R))*\})

更多信息请访问this answer

【讨论】:

  • 我无法添加每个级别..因为我有多个文件具有相同的功能-有时该功能可能会打开和关闭(例如..对于while循环或分组)这取决于功能的实现方式在这里,我只能猜测函数具有相同的名称和参数和{}
  • 如果可以确定最大嵌套层数,可以使用这个方案。
  • 有些语言允许嵌套运算符R,它允许您嵌套任意数量的级别。如果您的语言不支持它(Java 不支持,afaik PHP 和 Perl 支持),您将不得不预测最大嵌套级别或自己创建解析器。正则表达式,没有R 运算符,不能嵌套任意数量的级别。
【解决方案2】:

Regex 不擅长处理嵌套组件。但是,如果您知道@Override 的缩进与右大括号相同,并且其所有内容都进一步缩进,则可以使用:

([\t\s]+)@Override.*?\n\1}

【讨论】:

  • 我不能简单地添加这个......我想对其他一些具有相同定义的文件做同样的事情,但位置会发生变化
  • @Abin,仅仅因为你想要一些东西并不意味着 RegEx 可以完成它。我的意思是,它非常神奇的,但是......遗憾的是,它有局限性,这可能是最大的一个。
【解决方案3】:

恐怕仅使用正则表达式是不可能的。

如果您理解正确,您需要重新格式化一些语法,并且我认为代码必须仍然是可编译的,在这种情况下,您需要计算每个 { 的增加和每个 } 的减少,这样您就知道何时功能结束。另一种方法是在面临下一个声明时返回第一个找到的},但是会有很多异常需要处理,比如课程结束时等......

我建议您使用 Java 源代码解析来完成这项工作,它可以将方法识别为方法,并且可以节省大量工作,例如查看 javaparser

【讨论】:

  • 我不能简单地添加这个......我想对其他一些具有相同定义的文件做同样的事情,但位置会发生变化
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2011-07-24
相关资源
最近更新 更多