Java 从数学表达式中提取操作数的正则表达式
毫无疑问,这解决了我的特殊问题。我对正则表达式知之甚少。为此,我正在使用正则表达式类在Java中构建一个表达式解析器。我想从表达式中提取操作数、参数、运算符、符号和函数名,然后保存到ArrayList。目前我正在使用这种逻辑Java 从数学表达式中提取操作数的正则表达式,java,regex,parsing,mathematical-expressions,Java,Regex,Parsing,Mathematical Expressions,毫无疑问,这解决了我的特殊问题。我对正则表达式知之甚少。为此,我正在使用正则表达式类在Java中构建一个表达式解析器。我想从表达式中提取操作数、参数、运算符、符号和函数名,然后保存到ArrayList。目前我正在使用这种逻辑 String string = "2!+atan2(3+9,2+3)-2*PI+3/3-9-12%3*sin(9-9)+(2+6/2)" //This is just for testing purpose later on it will be provided by u
String string = "2!+atan2(3+9,2+3)-2*PI+3/3-9-12%3*sin(9-9)+(2+6/2)" //This is just for testing purpose later on it will be provided by user
List<String> res = new ArrayList<>();
Pattern pattern = Pattern.compile((\\Q^\\E|\\Q/\\E|\\Q-\\E|\\Q-\\E|\\Q+\\E|\\Q*\\E|\\Q)\\E|\\Q)\\E|\\Q(\\E|\\Q(\\E|\\Q%\\E|\\Q!\\E)) //This string was build in a function where operator names were provided. Its mean that user can add custom operators and custom functions
Matcher m = pattern.matcher(string);
int pos = 0;
while (m.find())
{
if (pos != m.start())
{
res.add(string.substring(pos, m.start()))
}
res.add(m.group())
pos = m.end();
}
if (pos != string.length())
{
addToTokens(res, string.substring(pos));
}
for(String s : res)
{
System.out.println(s);
}
问题是现在表达式可以包含用户定义格式的矩阵。对于函数,我想把每个矩阵都当作一个操作数或参数
投入1:
String input_1 = "2+3-9*[{2+3,2,6},{7,2+3,2+3i}]+9*6"
输出应为:
2
+
3
-
9
*
[{2+3,2,6},{7,2+3,2+3i}]
+
9
*
6
{[2,5][9/8,func(2+3)]}
+
9
*
8
/
5
<[2,9,2.36][2,3,2!]>
*
<[2,3,9][23+9*8/8,2,3]>
投入2:
String input_2 = "{[2,5][9/8,func(2+3)]}+9*8/5"
输出应为:
2
+
3
-
9
*
[{2+3,2,6},{7,2+3,2+3i}]
+
9
*
6
{[2,5][9/8,func(2+3)]}
+
9
*
8
/
5
<[2,9,2.36][2,3,2!]>
*
<[2,3,9][23+9*8/8,2,3]>
投入3:
String input_3 = "<[2,9,2.36][2,3,2!]>*<[2,3,9][23+9*8/8,2,3]>"
字符串输入_3=“*”
输出应为:
2
+
3
-
9
*
[{2+3,2,6},{7,2+3,2+3i}]
+
9
*
6
{[2,5][9/8,func(2+3)]}
+
9
*
8
/
5
<[2,9,2.36][2,3,2!]>
*
<[2,3,9][23+9*8/8,2,3]>
*
我希望现在ArrayList应该包含每个索引处的每个操作数、运算符、参数、函数和符号。如何使用正则表达式实现所需的输出。不需要表达式验证。对于正则表达式,您不能匹配任何级别的嵌套平衡括号 例如,在第二个示例中,
{[2,5][9/8,func(2+3)]}
您需要匹配左大括号和右大括号,但需要跟踪有多少个左大括号和右大括号/括号等。这不能用正则表达式来完成
另一方面,如果您简化了问题以消除任何平衡要求,那么您可能可以使用正则表达式进行处理。我认为您可以尝试以下方法:
(?<matrix>(?:\[[^\]]+\])|(?:<[^>]+>)|(?:\{[^\}]+\}))|(?<function>\w+(?=\())|(\d+[eE][-+]\d+)|(?<operand>\w+)|(?<operator>[-+\/*%])|(?<symbol>.)
备选方案说明:
-匹配给定 类型,不是该类型的右括号的字符 (所有内容均不包括右括号),以及 类型\[^\]+\]+\]+>\{[^\}]+\}
=数字,后跟\d+[eE][-+]\d+
或e
,后跟运算符e
或+
,后跟数字,以捕获元素,如-
2e+3
-匹配一个或多个单词字符\w+(?=\()
,如果是 后跟(A-Za-z0-9)
用于匹配函数,如(
sin
-匹配一个或多个单词字符\w+
,以进行匹配 操作数(A-Za-z0-9)
-匹配字符类中的一个字符,以匹配 操作员[-+\/*%]
-匹配任何其他字符,以匹配其他符号
将匹配任何字符,因此它必须是最后一个选项。与\w+(?=\()的情况类似
和\w+
,第二个将与前一个匹配,但是如果您不习惯区分函数和操作数,那么\w+
将足以匹配所有函数和操作数
在较长的示例中,零件
(?…)
在每个备选方案中,都是一个命名的捕获组,您可以在演示中看到它是如何在gorups中对匹配的片段进行分组的,例如:操作数、运算符、函数等。@trashgood我认为您提供的链接与我的问题无关。我是否可以说单词从这里开始,在这里结束,并在这两者之间匹配任何内容?我不确定如果要匹配第一个开始参数和最后一个结束参数之间的任何内容,可以执行以下操作(未测试):\((.*)\)
内部参数将是您想要的。非常感谢。工作很有魅力。正如我所说的,我对正则表达式的理解很弱,所以请告诉我这里发生了什么。@KamilMahmood我更新了答案,如果不够清楚,可以随意问:这些数字2e-3、2e+3、2e-3和2e+3没有得到正确的处理,XOR的目的是什么符号“^”。它们应该分开处理吗?^
是字符类中的一个否定,因此[^$]
意味着,除了$
之外的任何字符(如2e-3、2e+3、2e-3和2e+3)都是完整的数字,因此它们应该在一次传递中匹配。