我正在使用JTextPane
创建一个简单的IDE,并检测关键字并对其着色。
目前,我能够检测到:
我检测这些类型的方式是通过正则表达式。
现在,我正在尝试检测像[int x = 10;]这样的变量,并将它们着色为不同的颜色。
目前,我可以使用以下正则表达式获取所有数据类型,如int,float char:
Pattern words = Pattern.compile(\\bint\\b|\\bfloat\\b\\bchar\\b);
Matcher matcherWords = words.matcher(code);
while (matcherWords.find()) {
System.out.print(code.substring(matcherWords.start(), matcherWords.end());
// How to get next word that is a variable?
}
以下是我的程序的示例输出:
在检测到a
,b
等后,我如何能够检测c
,int
,float
等变量?
答案 0 :(得分:3)
您是否尝试过lookbehind / lookahead模式?
这种漫长的模式:
"(?<=int |float |String |double )([a-zA-Z_]\\w*)(?=,|;|\\s)|([a-zA-Z_]\\w*)(?=,|;|\\s*=)"
能够解析变量和逗号分隔的变量。
public static void main(String[] args) throws Exception {
String javaCode = "int a = 100;\n" +
"float b = 110;\n" +
"String c = \"Hello World\";" +
"double d, e, f, g = 1.0, h;";
Matcher matcher = Pattern
.compile("(?<=int |float |String |double )([a-zA-Z_]\\w*)(?=,|;|\\s)|([a-zA-Z_]\\w*)(?=,|;|\\s*=)")
.matcher(javaCode);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
结果:
a
b
c
d
e
f
g
h
此处也在regex101
进行了测试答案 1 :(得分:3)
试试这个:
(?:(?<=int|float|String|double|char|long)(?:\s+[a-zA-Z_$][\w$]*\s*)|(?<=\G,)(?:\s*[a-zA-Z_$][\w$]*\s*))(?=,|;|=)
表示:
(?<=int|float|String|double|char|long)
- 积极向后看
搜索变量类型,(?:\s+[a-zA-Z_$][\w$]*\s*)
- 非捕获组:至少一个空格,后跟有效
Java变量的字符,后跟零个或多个空格|
- 或; var之后加工名称之间的替代方案。输入或逗号后,(?<=\G,)
- 前一场比赛和逗号的正面观察(因为其他部分与两边的空格匹配)(?:\s*[a-zA-Z_$][\w$]*\s*)
- 非捕获组:至少一个空格,后跟有效
Java变量的字符,后跟零个或多个空格(?=,|;|=)
- 逗号,等号或分号的正面预测它使用\G
边界匹配(The end of the previous match),所以替代方法,即在其他名称之间搜索名称(确切地说是空格或/和逗号之间的单词),只有在它之后才匹配比赛。因此,它不会匹配字符串中逗号之间的每个单词。另外,我在$
中添加了[a-zA-Z_$][\w$]*
,因为它是变量名中的allowed,但不建议这样做。
对于Java:
Pattern pattern = Pattern.compile("(?:(?<=int|float|String|double|char|long)(?:\\s+[a-zA-Z_$][\\w$]*\\s*)|(?<=\\G,)(?:\\s*[a-zA-Z_$][\\w$]*\\s*))(?=,|;|=)");
修改强>
您可以使用(int |float |...)
直接使用matcher.start()
和matcher.end()
来匹配变量名称,但不要使用空格,但我宁愿在空间可以占用的每个地方使用(?:\s*)
然后检查数据处理过程中的冗余空间,因为你永远不会知道用户输入多少空格(当然多个空间是多余的,但它仍然有效!)。
另一个approuch是匹配空格但使用组,例如:
(?:(?<=int|float|String|double|char|long)(?:\s+)([a-zA-Z_$][\w$]*)(?:\s*)|(?<=\G,)(?:\s*)([a-zA-Z_$][\w$]*)(?:\s*))(?=,|;|=)
名称没有空格,但您需要从第1组和第1组中提取它们。 2 matcher.start(group no)
和matcher.end(group no)
。
EDIT2 回答评论中的问题
这取决于你想要达到的目标。如果您只想将变量作为字符串获取,则使用mathod trim()
就足够了,但如果您想在文本中获取变量的开始和结束索引,例如以不同的颜色突出显示它,那么最好是例如使用matcher.start(1)
来提取组1的起始索引。请考虑以下示例:
import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) throws IOException {
String text = "int a = 100;\n" +
"float b = 100.10;\n" +
"double c - 12.454545645;\n" +
"long longest dsfsf = 453543543543;\n" +
"a = d;\n" +
"char b = 'a';\n" +
"String str = \"dfssffdsdfsd\"\n" +
"int d,f,g;\n" +
"int a,f,frhg = 0;\n" +
"String string = \"a,b,c,d,e,f\"";
Pattern pattern = Pattern.compile("(?:(?<=int|float|String|double|char|long)(?:\\s+)([a-zA-Z_$][\\w$]*)(?:\\s*)|(?<=\\G,)(?:\\s*)([a-zA-Z_$][\\w$]*)(?:\\s*))(?=,|;|=)");
Matcher matcher = pattern.matcher(text);
while(matcher.find()){
System.out.println("trim(): " + text.substring(matcher.start(),matcher.end()).trim()); // cut off spaces by trim() method;
int group = (matcher.group(1)==null)? 2 : 1; // check which group captured string;
System.out.println("group(" + group + "): \n\t" // to extract string by group capturing;
+ text.substring(matcher.start(group),matcher.end(group))
+ ",\n\tsubstring(" + matcher.start(group) + "," + matcher.end(group)+")");
}
}
}
输出呈现两个方法。
答案 2 :(得分:0)
\b(?:int|float|String|char|double|long)\b\s+([^=;]+)
您是否尝试仅匹配变量名称?如果是,则上述内容将有所帮助。