【问题标题】:Regex function to find specific depth in recursive正则表达式函数以递归方式查找特定深度
【发布时间】:2021-12-18 23:28:18
【问题描述】:

我有以下场景,我应该在一行代码上使用正则表达式(Java/PCRE)并剥离某些定义的函数,并且只增强该函数的值,如下例所示:

输入 ArrayNew(1) = adjustalpha(shadowcolor, CInt(Math.Truncate (ObjectToNumber (Me.bezierviewshadow.getTag))))

输出:替换正则表达式

ArrayNew(1) = adjustalpha(shadowcolor, Me.bezierviewshadow.getTag)

这里的 CInt、Math.Truncate 和 ObjectToNumber 被删除,保留在输出中,如上所示

函数 CInt、Math.Truncate 不断更改为 CStr 或 Math.Random 等,因此无法对正则表达式查询进行硬编码。

我在 stackoverflow 上尝试了很多选项,但大多数都不起作用。

如果查询是可定制的,就像 Cint 返回 CInt 所指的所有函数一样,那就太好了。 ( 找到一个文本,然后是第一个 ( 和 ) 之间的所有内容,忽略中间的平衡括号对。

【问题讨论】:

  • 自己写一个小解析器并在这里计算括号可能更容易。

标签: java regex recursion


【解决方案1】:

我知道这不漂亮,但使用原始正则表达式是你的错 :)

@Test
void unwrapCIntCall() {
    String input = "ArrayNew(1) = adjustalpha(shadowcolor, CInt(Math.Truncate (ObjectToNumber (Me.bezierviewshadow.getTag))))";
    String expectedOutput = "ArrayNew(1) = adjustalpha(shadowcolor, Me.bezierviewshadow.getTag)";

    String output = input.replaceAll("CInt\\s*\\(\\s*Math\\.Truncate\\s*\\(\\s*ObjectToNumber\\s*\\(\\s*(.*)\\s*\\)\\s*\\)\\s*\\)", "$1");
    assertEquals(expectedOutput, output);
}

现在解释一下; \\s* 部分允许任意数量的任何空白字符,无论它们在哪里。在模式中,我在中间使用了(.*),这意味着我匹配那里的任何东西,但这很好*。我使用(.*) 而不是.*,以便将特定部分捕获为捕获组$1(因为$0 始终是整个匹配项)。有趣的部分被捕获,我可以在替换字符串中引用它们。

*只要您在一个字符串中没有多个这样的分配。否则,您应该将字符串分解为仅包含一个此类分配的部分,并对每个字符串应用此替换。或者,尝试(.*?) 而不是(.*),它会为我编译 - AFAIK 使.* 匹配尽可能少的字符。

如果实际调用的方法不同,则将它们在正则表达式中的名称替换为您期望的变体,例如将CInt 替换为(?CInt|CStr),将Math\\.Truncate 替换为Math\\.(?Truncate|Random) 等(使用(? 而不是( 使该组不被捕获,因此它们不会占用 $1$2 等插槽。

如果这变得太复杂,那么您应该考虑是否真的想使用正则表达式来完成,或者使用普通字符串方法编写一个相对较长的函数是否更容易,例如indexOf 和@987654340 @ :)

奖金;如果绝对一切都不同,但调用深度,那么你可以试试这个:

String output = input.replaceAll("[\\w\\d.]+\\s*\\(\\s*[\\w\\d.]+\\s*\\(\\s*[\\w\\d.]+\\s*\\(\\s*(.*)\\s*\\)\\s*\\)\\s*\\)", "$1");

是的,读起来绝对是一场噩梦,但据我所知,你是在追赶这个怪物 :)

您可以使用([^()]*) 而不是(.*) 来防止更深的嵌套表达式。请注意,对深度的精细控制是日常正则表达式的真正弱点。

【讨论】:

  • [\\w\\d.]+\\s*\(\\s*[\\w\\d.]+\\s*\(\\s*[\ \w\\d.]+\\s*\(\\s*(.*)\\s*\)\\s*\)\\s*\) 这是什么味道?不适用于测试字符串上的 Java 或 PCRE
  • @mohsyn 简单的 Java 正则表达式,我什至没有使用任何特殊功能。确保 IDE 在粘贴时不会再次转义每个 \ 字符,它应该完全按照我编写的方式查看代码。我在发布之前运行过它,它对我来说很好用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 2021-06-16
  • 2020-04-12
  • 2021-12-31
  • 2012-01-16
相关资源
最近更新 更多