你如何引用重复的嵌套捕获组?

时间:2015-02-15 05:05:53

标签: java regex

我正在编写Java代码,并且最近将此list-of-actions类中的一些方法委托给BasicActions类,现在想要更新此类中的所有方法,而不是引用BasicActions方法。我正在更新的方法和我希望它们引用的方法具有相同的名称和参数,我正在尝试使用正则表达式重写代码,但我无法弄清楚如何处理方法参数,可能有任何数字,我不能简单地复制组群,因为我需要从中删除关键字。

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));
}

请参阅https://regex101.com/r/uE7aA1/1

中的几乎解决方案

我的问题是因为我不能在这种情况下包含type关键字(double),所以我必须拆分变量名,然后多次捕获它们。如何访问多个捕获,或者在复制多个参数时重新格式化这些参数?

2 个答案:

答案 0 :(得分:1)

重复捕获组时,仅捕获最后一项。使用正则表达式

public void ([a-zA-Z]*)\((?:(?:final )?[a-zA-Z]+ ([a-zA-Z]+(?:, )?))*\)  

其中(?:)用于避免不必要的捕获复杂性和来自地狱的编号,$ 0是整体,$ 1是“jumpTo”而$ 2是“y”。不幸的是,x无法以这种方式捕获。

你可能需要通过多次重复参数匹配来爆炸正则表达式,我在这里做了3次(你可能需要更多),

public void([a-zA-Z] *)((?:( ?: final)?[a-zA-Z] +([a-zA-Z] +(?:,)?)) (?:(?:final)?[a-zA-Z] +([a-zA-Z] +(?:,)?))?(?:(?:final)?[a-zA-Z ] +([a-zA-Z] +(?:,)?))?)

$ 1是“Jumpto”,$ 2是“x”,$ 3是“y”而$ 4是空的“”

编号很简单,因为不计算非捕获组。

/ *任意代码* /可以使用

更简单地匹配非捕获规则
\{(?:.|\n)*?\n    \} 

和替换规则

{\n    addAction(BasicActions.$1($2$3$4$5$6$7));\n    }\n

最多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,...参数,具有更长的正则表达式,并且在计算捕获组时没有问题。 last()()..确保捕获组为空,而不管参数的数量(这取决于正则表达式引擎实现)。一些正则表达式引擎可能不喜欢empty(),但很少有人检测到空字符串的自愿匹配

((?x:))

对捕获组的正则表达式评论。

(由于拼写错误和外观而多次编辑,(。| \ n)是半盲人阅读曲折正则表达式的笑脸)

答案 1 :(得分:0)

除了最后的顺序之外,不可能引用重复的捕获组;因此,如果要修改每个捕获组,则必须按顺序应用多个正则表达式:

步骤1:将参数列表复制到位(https://regex101.com/r/uE7aA1/2

pattern: (public void (\w+\((?:(?:final )?\w+ \w+(?:, )?)*\))) \{(?:.|\n)*?\n    \}
replacement: $1 {\n        addAction(BasicActions.$2);\n    }
output:
public void jumpTo(final double x, double y) {
    addAction(BasicActions.jumpTo(final double x, double y));
}

第2步:删除final

pattern:final #note the space
replacement:
output:
public void jumpTo(double x, double y) {
    addAction(BasicActions.jumpTo(double x, double y));
}

第3步:删除类型关键字(https://regex101.com/r/kC0nA3/3

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));
}