如何使用正则表达式重新排列方法访问修饰符
how to rearrange method access modifier using regex
我是正则表达式的新手。
我正在尝试使用正则表达式为声纳重新排列方法访问修饰符 Rule
(public|protected|private)|(abstract|static)|(final)|(volatile)|(synchronized)|(native)|(strictfp)
输入示例
static public void main(String[] args)
然后使用
</code> <br> 替换,但我得到相同的结果。 </p>
<p>输出应该按照正确的访问修饰符顺序,例如首先 public 然后是静态的:<br>
<code>public static void main (String[] args)
方法签名应遵循以下顺序:
public or protected or private
然后如果适用
abstract or static
然后如果适用
final
然后如果适用
volatile
然后如果适用
synchronized
然后如果适用
native
然后如果适用
stictfp
你所拥有的基本上就是你所需要的,你只需要将碎片拼凑起来。正则表达式应该是
(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} to get the capture groups, then rearrange them manually, making sure to use 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
问题是您的 (…)|(…)|(…)|…
形式的模式指定了备选方案,而只有一个必须匹配。因此,您的模式一次只匹配一个关键字,其中一组包含匹配的关键字,而所有其他组为空。然后,当您将该匹配项替换为 </code> 时,您将替换关键字本身,其他组没有任何效果。反复应用操作仍然没有效果。</p>
<p>因此您需要一个匹配整个关键字序列的模式,填充存在关键字的组。为此,请使用 <code>+
量词将您的正则表达式包含在另一组中,以匹配至少一个关键字,但尽可能多。重复组中的捕获组的好处是,如果他们在下一次重复中不匹配,他们会一直记住上一次匹配。因此,在识别重复组的匹配项后,如果序列中有一个关键字,则每个子组都捕获了一个关键字。
所以最终的模式可能看起来像
(?:\b((?:public|protected|private)\s+)|((?:abstract|static)\s+)|(final\s+)|((?:volatile|synchronized)\s+)|((?:native|strictfp)\s+))+
在这里,我确定了更多的互斥关键字,将数量减少到五组。我在组中包含了后续的 white-space(使用像 ((?:keyword1|keyword2)\s+)
这样的子模式,在非捕获组中列出备选方案)。这样,替换中就会有正确的间距。我在开头添加了一个单词边界(\b
)以确保没有错误匹配(例如单词nonstatic
)。由于强制性的 white-space.
,关键字后的单词边界已经隐含
在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+)"
+ ")+",
""
);
System.out.println(out);// public static final synchronized native void main(String[] args)
但请注意,这有局限性。对于 Java 语言,注释是修饰符,因此可以与关键字修饰符自由混合,例如static @Deprecated public
。由于注释具有递归语法(注释可能包含注释,但即使是更简单的情况,如嵌套常量表达式或数组初始化器也可能具有不同的深度),不可能通过单个正则表达式解析所有有效的注释值。所以上面的解决方案只处理关键字,无论您添加多少注释案例,您总是必须在某处进行切割,考虑到其他所有内容均不受支持。
我是正则表达式的新手。 我正在尝试使用正则表达式为声纳重新排列方法访问修饰符 Rule
(public|protected|private)|(abstract|static)|(final)|(volatile)|(synchronized)|(native)|(strictfp)
输入示例
static public void main(String[] args)
然后使用 </code> <br> 替换,但我得到相同的结果。 </p>
<p>输出应该按照正确的访问修饰符顺序,例如首先 public 然后是静态的:<br>
<code>public static void main (String[] args)
方法签名应遵循以下顺序:
public or protected or private
然后如果适用
abstract or static
然后如果适用
final
然后如果适用
volatile
然后如果适用
synchronized
然后如果适用
native
然后如果适用
stictfp
你所拥有的基本上就是你所需要的,你只需要将碎片拼凑起来。正则表达式应该是
(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} to get the capture groups, then rearrange them manually, making sure to use 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
问题是您的 (…)|(…)|(…)|…
形式的模式指定了备选方案,而只有一个必须匹配。因此,您的模式一次只匹配一个关键字,其中一组包含匹配的关键字,而所有其他组为空。然后,当您将该匹配项替换为 </code> 时,您将替换关键字本身,其他组没有任何效果。反复应用操作仍然没有效果。</p>
<p>因此您需要一个匹配整个关键字序列的模式,填充存在关键字的组。为此,请使用 <code>+
量词将您的正则表达式包含在另一组中,以匹配至少一个关键字,但尽可能多。重复组中的捕获组的好处是,如果他们在下一次重复中不匹配,他们会一直记住上一次匹配。因此,在识别重复组的匹配项后,如果序列中有一个关键字,则每个子组都捕获了一个关键字。
所以最终的模式可能看起来像
(?:\b((?:public|protected|private)\s+)|((?:abstract|static)\s+)|(final\s+)|((?:volatile|synchronized)\s+)|((?:native|strictfp)\s+))+
在这里,我确定了更多的互斥关键字,将数量减少到五组。我在组中包含了后续的 white-space(使用像 ((?:keyword1|keyword2)\s+)
这样的子模式,在非捕获组中列出备选方案)。这样,替换中就会有正确的间距。我在开头添加了一个单词边界(\b
)以确保没有错误匹配(例如单词nonstatic
)。由于强制性的 white-space.
在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+)"
+ ")+",
""
);
System.out.println(out);// public static final synchronized native void main(String[] args)
但请注意,这有局限性。对于 Java 语言,注释是修饰符,因此可以与关键字修饰符自由混合,例如static @Deprecated public
。由于注释具有递归语法(注释可能包含注释,但即使是更简单的情况,如嵌套常量表达式或数组初始化器也可能具有不同的深度),不可能通过单个正则表达式解析所有有效的注释值。所以上面的解决方案只处理关键字,无论您添加多少注释案例,您总是必须在某处进行切割,考虑到其他所有内容均不受支持。