Java 如何引用重复的嵌套捕获组?
我正在编写Java代码,最近将这个actions类列表中的一些方法委托给了一个BasicActions类,现在我想更新这个类中的所有方法,以引用BasicActions方法。我正在更新的方法和我希望它们引用的方法具有相同的名称和参数,我尝试使用regex重写代码,但我不知道如何处理方法参数,其中可能有任意数量的参数,我不能简单地复制组,因为我需要从中删除关键字Java 如何引用重复的嵌套捕获组?,java,regex,Java,Regex,我正在编写Java代码,最近将这个actions类列表中的一些方法委托给了一个BasicActions类,现在我想更新这个类中的所有方法,以引用BasicActions方法。我正在更新的方法和我希望它们引用的方法具有相同的名称和参数,我尝试使用regex重写代码,但我不知道如何处理方法参数,其中可能有任意数量的参数,我不能简单地复制组,因为我需要从中删除关键字 Example input: public void jumpTo(final double x, double y) { /*
Example input:
public void jumpTo(final double x, double y) {
/*arbitrary code,
possibly spanning multiple lines*/
}
Desired output:
public void jumpTo(double x, double y) {
addAction(BasicActions.jumpTo(x, y));
}
Almost-correct solution:
pattern: (public void ([a-zA-Z]*)\(((final )?([a-zA-Z]+) ([a-zA-Z]+(, )?))*\) \{\n *)((.*\n)*?)( })
replacement: $1addAction(BasicActions.$2($6));\n$10
Almost-correct output: (doesn't remove unnecessary 'final' keywords, only captures the final argument)
public void jumpTo(final double x, double y) {
addAction(BasicActions.jumpTo(y));
}
请参阅上的“几乎解决方案”
我的问题是,因为我不能包含type关键字(
double
,在本例中),我必须拆分变量名,然后多次捕获它们。如何访问多个捕获,或者在复制多个参数时重新格式化这些参数?重复捕获组时,只捕获最后一项。使用正则表达式
public void ([a-zA-Z]*)\((?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))*\)
其中(?:)用于避免不必要的捕获复杂性和地狱中的编号,$0表示全部,$1表示“跳转”,而$2表示“y”。不幸的是,x不能以这种方式捕获
您可能需要分解正则表达式,通过多次重复参数匹配,我在这里做了3次(您可能需要更多)
公共空间([a-zA-Z]*)((?:(?:最终版);[a-zA-Z]+(?:,))(?:(?:最终版);[a-zA-Z]+([a-zA-Z]+(?:,)最终版);(?:(?:最终版);[a-zA-Z]+(?:,)?)
$1为“跳转”,$2为“x”,$3为“y”,$4为空
编号很简单,因为不计算非捕获组
/*任意代码*/可以使用更简单的匹配非捕获规则
\{(?:.|\n)*?\n \}
以及替换规则
{\n addAction(BasicActions.$1($2$3$4$5$6$7));\n }\n
最终的regexp(最多6个参数)将是(在多行上拆分)
(?x: header match starts from here)
(public void ([a-zA-Z]*)\(
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 1)
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 2)
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 3)
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 4)
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 5)
(?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))?(?x: param 6)
\))
(?x: match body starts here) \{(.|\n)*?\n \}
()()()()()()(?x: for missing params 1-6)
在哪里
$1是原始函数原型
$2是取自函数名的名称
$3是第一个参数(或空字符串)
$4是第二个参数(或空字符串)
$5是第三个参数(或空字符串)
使用更长的正则表达式很容易扩展到4,5,6,7,…参数,并且在计算捕获组时没有问题。最后一个()()…确保捕获组为空,而不管参数的数量如何(这取决于正则表达式引擎的实现)。一些正则表达式引擎可能不喜欢空(),但很少有人检测到空字符串的自愿匹配
((?x:))
将regexp注释添加到捕获组中
(由于拼写错误和外观原因,编辑了很多次,(.|\n)是半盲半盲阅读复杂正则表达式的笑脸)除了顺序中的最后一个之外,不可能引用重复的捕获组;因此,如果要修改每个捕获组,如在这种情况下,必须按顺序应用多个正则表达式: 步骤1:将参数列表复制到位置() 步骤2:删除
final
pattern:final #note the space
replacement:
output:
public void jumpTo(double x, double y) {
addAction(BasicActions.jumpTo(double x, double y));
}
步骤3:删除类型关键字()
不能使用正则表达式返回重复捕获组。如果在捕获组后放置类似
*
或+
或{1,5}
的内容,则组(n)
方法将为您提供组匹配的源的最后一个子字符串。(这同样适用于替换字符串中的$
,该字符串使用组(n)
)该组匹配的任何早期子字符串都将丢失。抱歉。如果您所要求的与此无关,那么我不理解您的要求。很难理解您的需要。您无法使用regexp处理嵌套的{}()[]..,对于包含部分代码的注释也会非常复杂。您可以插入addAction()调用,并插入返回语句,并且不应尝试匹配“.任意代码,可能跨越多行”使用正则表达式….@Pierre,代码的格式很好;可以安全地假设代码以包含四个空格和一个右括号的行结尾,就像在我的解决方案中一样。
pattern:final #note the space
replacement:
output:
public void jumpTo(double x, double y) {
addAction(BasicActions.jumpTo(double x, double y));
}
use lookahead to match any argument without passing over other arguments
pattern: \w+ (\w+)(?=(, \w+ \w+)*\)\);\n })
replacement: $1
output:
public void jumpTo(double x, double y) {
addAction(BasicActions.jumpTo(x, y));
}