Java 使用正则表达式从代码语句中提取变量
我试图从代码语句和“if”条件中提取变量。我有一个正则表达式,但是Java 使用正则表达式从代码语句中提取变量,java,regex,pattern-matching,Java,Regex,Pattern Matching,我试图从代码语句和“if”条件中提取变量。我有一个正则表达式,但是mymatcher.find()不会返回任何匹配的值。 我不知道怎么了 这是我的密码: import java.util.regex.Matcher; import java.util.regex.Pattern; public class test { public static void main(String[] args) { String test="x=y+z/n-10+my5th_integ
mymatcher.find()
不会返回任何匹配的值。
我不知道怎么了
这是我的密码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test {
public static void main(String[] args) {
String test="x=y+z/n-10+my5th_integer+201";
Pattern mypattern = Pattern.compile("^[a-zA-Z_$][a-zA-Z_$0-9]*$");
Matcher mymatcher = mypattern.matcher(test);
while (mymatcher.find()) {
String find = mymatcher.group(1) ;
System.out.println("variable:" + find);
}
}
}
您需要删除分别在字符串开头和结尾声明位置的
^
和$
锚,并使用mymatcher.group(0)
而不是mymatcher.group(1)
,因为您的正则表达式中没有任何捕获组:
String test="x=y+z/n-10+my5th_integer+201";
Pattern mypattern = Pattern.compile("[a-zA-Z_$][a-zA-Z_$0-9]*");
Matcher mymatcher = mypattern.matcher(test);
while (mymatcher.find()) {
String find = mymatcher.group(0) ;
System.out.println("variable:" + find);
}
看,结果是:
variable:x
variable:y
variable:z
variable:n
variable:my5th_integer
通常只使用正则表达式处理源代码会失败。 如果您只想挑选标识符(我们将在下面进一步讨论变量),那么您就有机会使用正则表达式(毕竟,这就是lexer的构建方式) 但是你可能需要一个比你现在拥有的更复杂的版本,即使有其他作者建议的修改 第一个问题是,如果您允许使用任意语句,它们通常具有看起来像标识符的关键字。在您的特定示例中,“if”看起来像一个标识符。因此,您的匹配器要么必须识别类似于子字符串的标识符,然后减去已知的关键字,要么正则表达式本身必须表示标识符具有基本形状,但不能看起来像特定的关键字列表。(后者称为减法正则表达式,在大多数正则表达式引擎中找不到。它看起来像:
[a-zA-Z_$][a-zA-Z_$0-9]* - (if | else | class | ... )
我们的DMS词法生成器[见我的简历]有减法正则表达式,因为这在语言词法分析中非常有用)
如果“关键字”不总是关键字,这会变得更复杂,也就是说,
它们只能是特定上下文中的关键字。Java“关键字”枚举就是这样的:如果在类型上下文中使用它,它就是一个关键字;否则它是一个标识符;C#类似。现在唯一知道的方法
如果一个声称的标识符是一个关键字,那么它将实际解析代码(这就是您检测控制其关键字的上下文的方式)
接下来,Java中的标识符允许使用各种Unicode字符(拉丁语、俄语、汉语等)。regexp可以识别这些字符,它比您提出的简单的“a-Z”样式大得多
对于Java,您需要防范包含变量名的字符串文本。考虑(有趣但有效的)陈述:
a = "x=y+z/n-10+my5th_integer+201";
\u0061 = \u0062; // means "a=b;"
a = $"x+{y*$"z=${c /* p=q */}"[2]}*q" + b;
这里只有一个标识符。注释也会出现类似的问题
包含类似于语句的内容:
/* Tricky:
a = "x=y+z/n-10+my5th_integer+201";
*/
对于Java,您也需要担心Unicode转义。考虑这个有效的java语句:
a = "x=y+z/n-10+my5th_integer+201";
\u0061 = \u0062; // means "a=b;"
a = $"x+{y*$"z=${c /* p=q */}"[2]}*q" + b;
或更恶劣:
a\u006bc = 1; // means "akc=1;" not "abc=1;"!
如果没有Unicode字符解码,您甚至可能
注意一个字符串。以下是上述的一个变体:
a = \u0042x=y+z/n-10+my5th_integer+201";
要正确提取标识符,您需要构建(或使用)完整Java lexer的等价物,而不仅仅是简单的正则表达式匹配
如果你不在乎大多数时候是对的,你可以试试你的正则表达式。通常应用于源代码解析的正则表达式的结果很糟糕,部分原因是上述问题(例如,过于简化)
您很幸运,因为您正在尝试为Java做一些事情。如果必须为C#语言(一种非常类似的语言)执行此操作,则必须处理插值字符串,这允许字符串中包含表达式。表达式本身可以包含字符串。。。它的乌龟一路下来。考虑C(6)语句:
a = "x=y+z/n-10+my5th_integer+201";
\u0061 = \u0062; // means "a=b;"
a = $"x+{y*$"z=${c /* p=q */}"[2]}*q" + b;
它包含标识符a、b、c和y。其他每一个“标识符”实际上只是一个字符串或注释字符。PHP具有类似的插值字符串
要从中提取标识符,您需要一个能够理解字符串元素嵌套的工具。词法分析器通常不做递归(我们的DMS词法分析器处理这个问题,正是因为这个原因),所以要正确处理这个问题,通常需要一个解析器,或者至少需要一些跟踪嵌套的东西
还有一个问题:是否只提取变量名?
如果标识符表示方法、类型、类或包,该怎么办?
如果没有完整的解析器和完整的Java名称和类型解析,您就无法理解这一点,您必须在找到该语句的上下文中完成这一点。你会惊讶于需要多少代码才能做到这一点
所以,如果你的目标很简单,你不在乎它是否能解决这些复杂问题,你可以用一个简单的正则表达式来挑选一些东西
看起来像是标识符
如果您想很好地使用它(例如,在某些生产代码中使用它),那么单个正则表达式将是一场灾难。你将用一生的时间向用户解释他们无法键入的内容,而这永远不会起作用
摘要:由于所有的复杂性,通常只使用正则表达式处理源代码都会失败。人们不断地重新吸取教训。词法生成器广泛应用于语言处理工具中,这是一个关键原因。字符串中的第二个字符是
=
,但您的正则表达式不允许任何=
。你的正则表达式也没有任何组。我不知道“=”将如何影响正则表达式,因为我对正则表达式是全新的。我使用了.start()和.end(),但也不起作用,在这个例子中,我希望x、y、z、n和my5th_整数是结果,因为它们是变量。这是一个很好的解释,您肯定是对的,但出于我的目的,我只需要上面的正则表达式,因为我正在对伪代码进行数据流分析,我只需要提取变量名称,我唯一关心的关键字是:if、else、elseif、true和false,这样我就可以轻松地处理它们了。你说的是Java:}如果你想进行数据流分析(不清楚这在psuedocode中有什么用处),你仍然需要解析和进行名称解析。请参阅我关于“解析后的生活”的文章(谷歌或via bio)。从根本上说,我们回到了“你打算制造一个玩具(用于教育目的)”,这意味着只要你明白你在作弊,任何作弊都是可以的,或者