我知道这不漂亮,但使用原始正则表达式是你的错 :)
@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");
是的,读起来绝对是一场噩梦,但据我所知,你是在追赶这个怪物 :)
您可以使用([^()]*) 而不是(.*) 来防止更深的嵌套表达式。请注意,对深度的精细控制是日常正则表达式的真正弱点。