我是regex的新手。我尝试使用正则表达式为sonar Rule重新安排方法访问修饰符
(public|protected|private)|(abstract|static)|(final)|(volatile)|(synchronized)|(native)|(strictfp)
将输入示例作为
static public void main(String[] args)
,然后使用
$1$2$3$4$5$6$7
但是我得到了同样的结果。
输出应该是正确的访问修饰符顺序,比如首先是public,然后是static:
public static void main (String[] args)
方法签名应遵循以下顺序:
如果适用,则为public or protected or private
如果适用,则为abstract or static
如果适用,则为final
如果适用,则为volatile
如果适用,则为synchronized
如果适用,则为native
stictfp
发布于 2018-08-22 02:10:48
问题是表单(…)|(…)|(…)|…
的模式指定了备选方案,而只有一个必须匹配。因此,您的模式一次只匹配一个关键字,其中一个组包含匹配的关键字,所有其他组都为空。然后,当您将该匹配替换为$1$2$3$4$5$6$7
时,您就是将该关键字替换为其本身,而其他组不起任何作用。重复应用该操作仍然没有任何效果。
因此,您需要一个匹配整个关键字序列的模式,填充其关键字所在的组。为此,使用+
量词将您的正则表达式包含在另一个组中,以匹配至少一个关键字,但与存在的关键字一样多。在重复组中捕获组的好处是,如果它们在下一次重复中不匹配,它们会一直记住前一次匹配。因此,在识别重复组的匹配之后,每个子组都捕获了一个关键字,如果序列中有一个关键字的话。
因此,生成的模式可能如下所示
(?:\b((?:public|protected|private)\s+)|((?:abstract|static)\s+)|(final\s+)|((?:volatile|synchronized)\s+)|((?:native|strictfp)\s+))+
在这里,我确定了更多的互斥关键字,将数量减少到五个组。我在组中包含了随后的空格(使用子模式,如((?:keyword1|keyword2)\s+)
,在非捕获组中列出备选方案)。这样,在替换中就会有正确的间距。我在开头添加了一个单词边界(\b
),以确保没有错误匹配(例如单词nonstatic
)。由于必须使用空格,关键字之后的单词边界已经隐含。
在Java代码中:
String in = "synchronized public final static native void main(String[] args)";
String out = in.replaceAll(
"(?:\\b"
+ "((?:public|protected|private)\\s+)|((?:abstract|static)\\s+)|"
+ "(final\\s+)|((?:volatile|synchronized)\\s+)|((?:native|strictfp)\\s+)"
+ ")+",
"$1$2$3$4$5"
);
System.out.println(out);// public static final synchronized native void main(String[] args)
但请注意,这是有局限性的。对于Java语言来说,注释是修饰符,因此可以自由地与关键字修饰符混合,例如static @Deprecated public
。由于批注具有递归语法(批注可能包含批注,但即使是嵌套常量表达式或数组初始化器等更简单的情况也可能具有不同的深度),因此不可能通过一个正则表达式解析所有有效的批注值。因此,上面的解决方案只处理关键字,无论您可能添加多少注释案例,您总是必须在某个地方进行切割,考虑到其他所有内容都不受支持。
发布于 2018-08-18 19:45:50
你所拥有的基本上就是你所需要的,你只需要把它们拼凑在一起。正则表达式应该是
(public|protected|private)|(abstract|static)|(final)|(volatile)|(synchronized)|(native)|(strictfp)
捕获组索引决定了哪些内容应该放在哪里。如果你能捕获整个方法签名,即。
static public void main(String[] args)
作为字符串,则上面的正则表达式将在捕获组1中捕获public
,在捕获组2中捕获static
。Try it out here!
使用java.util.regex.{Pattern,Matcher}获取捕获组,然后手动重新排列它们,确保使用String.trim()删除多余的空格。
这是一个可行的解决方案
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Signature {
public static void main(String[] args) {
// slightly more complex example to show off capabilities of method
String oldSignature = "synchronized static final native public void barFooer(int foo, double bar)";
// echo to user
System.out.printf("%nOriginal method signature:%n %s%n%n", oldSignature);
// group number ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ( 7 )
String regex = "(public|protected|private)|(abstract|static)|(final)|(volatile)|(synchronized)|(native)|(strictfp)";
// create regex.Pattern and regex.Matcher objects
Pattern pat = Pattern.compile(regex);
Matcher mat = pat.matcher(oldSignature);
// array to hold signature "groups" in correct order
String[] groups = new String[7];
// int to hold end of last matched group
int endOfLastGroup = -1;
while (mat.find()) {
for (int gg = 1; gg <= 7; ++gg) {
// get the new matched group and any previous match in this group
String newGroup = mat.group(gg);
String oldGroup = groups[gg-1];
// where does the new matched group end?
int endOfNewGroup = mat.end();
// did we find a new match in this group?
if (newGroup != null) {
// cannot have, for instance, both "public" and "private"
if (oldGroup != null) {
System.err.printf("Error! Signature cannot contain both '%s' and '%s'!%n", newGroup.trim(), oldGroup.trim());
return;
}
// otherwise, new group found!
groups[gg-1] = newGroup;
// find furthest-right matched group end
if (mat.end() > endOfLastGroup)
endOfLastGroup = mat.end();
} } }
// new signature will be constructed with a StringBuilder
StringBuilder newSignature = new StringBuilder("");
// add groups to new signature in correct order
for (String group : groups) {
if (group != null) {
newSignature.append(group.trim());
newSignature.append(" ");
} }
// finally, add the return type, method name, arguments, etc.
newSignature.append(oldSignature.substring(endOfLastGroup).trim());
// echo to user
System.out.printf("New method signature:%n %s%n%n", newSignature.toString());
}
}
示例输出:
17:34 |aww@airy test| javac Signature.java
17:35 |aww@airy test| java Signature
Original method signature:
synchronized static final native public void barFooer(int foo, double bar)
New method signature:
public static final synchronized native void barFooer(int foo, double bar)
此代码也可从以下要点获得:https://gist.github.com/awwsmm/85575d2756f69b95564ff11b8ee105fd
https://stackoverflow.com/questions/51907956
复制相似问题