我目前负责验证给定表达式的格式是否正确。例如“ 7x ^ 2 + 2x +1”会通过,但“ 7x72”或格式错误的内容会失败。
\d*x{0,1}(\^\d*){0,1}
它检查每个函数,系数,可选x,可选指数是否存在。我只是不确定如何格式化它,以便它对于+/-号之间的每个部分都必须正确,否则该功能将无法正确键入。
如何解决此问题?
答案 0 :(得分:2)
TL; DR 正则表达式为:
(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?
完整语法为:
[ ['-'][number]'x^2' ] ['+' | '-'] [ ['-'][number]'x' ] ['+' | '-'] [ ['-']number ]
['-']
表示数字的可选减号。
[number]
是因为1
的乘数可以省略,即使它是-1
,例如-x
是-1x
的有效简写。
['+' | '-']
表示+
或-
,标记为可选以使其简单,但实际上在部分之间是必需的,而本身是不允许的。这是使正则表达式变大的棘手部分。
因此,让我们进行构建:
part1: -?\d*x\^2
part2: -?\d*x
part3: -?\d+
OP : \s*[+-]\s*(?!-)
(?!-)
是为了防止在运算符之后出现减号。
剩下的是[part1] [OP] [part2] [OP] [part3]
,其中包含3个可选部分和两个可选运算符,不同之处在于部分必须由运算符分隔,并且运算符必须位于各部分之间,并且必须存在至少一个部分。
为确保存在某些内容,我们只需要防止空字符串,即以(?!$)
开头的正则表达式,即字符串结尾处的零负负前瞻,也就是“在输入开始时,不在输入末尾。”
在正则表达式中,我们使用(?: xxx )?
进行可选操作,即将一个非捕获组标记为可选,因此使每个部分和操作员都变得很容易。
到目前为止,我们有:
(?!$)(?:part1)?(?:OP)?(?:part2)?(?:OP)?(?:part3)?
现在开始处理棘手的部分:
零件必须由操作员分隔
这是最简单的测试,方法是确保part2不紧跟2
(part1的最后一个字符),并且part3不紧跟2
或x
(part1或part2的最后一个字符),因此我们将使用零宽度的负向后查找。
(?:(?<!2)part2)
(?:(?<![2x])part3)
操作员必须在零件之间
操作员不能是第一位或最后一位
(?:(?<!^)OP(?!^))
操作员不能相邻,要确保第二个操作员前面紧跟着part1或part2,这是最简单的测试,这使得“不在开始时”变得多余。
(?:(?<=[2x])OP)
为了保持一致,可以将第一位操作员的“不是从一开始”更改为“必须是part1”。
(?:(?<=2)OP)
现在可以给我们了(显示在多行上可以澄清):
(?!$)
(?:part1)?
(?:(?<=2)OP(?!^))?
(?:(?<!2)part2)?
(?:(?<=[2x])OP(?!^))?
(?:(?<![2x])part3)?
全部结合在一起,并添加了捕获组以捕获(带符号的)数字和运算符
(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?
这里是用Java编码的逻辑,用于在公式a
中查找b
,c
和ax^2 + bx + c
:
public static void main(String[] args) {
System.out.println("part1 op1 part2 op2 part3 a b c input");
test("3x^2 + 4x + 5");
test("x^2 + x + 1");
test("x^2 - 4x");
test("-x^2 - 1");
test("-4x - 5");
test("-3x^2");
test("-4x");
test("-5");
test("");
test("-3x^2 + -1x");
}
private static void test(String input) {
String regex = "(?!$)" +
"(?:(-?\\d*)x\\^2)?" +
"(?:(?<=2)\\s*([+-])\\s*(?!-|^))?" +
"(?:(?<!2)(-?\\d*)x)?" +
"(?:(?<=[2x])\\s*([+-])\\s*(?!-|^))?" +
"(?:(?<![2x])(-?\\d+))?";
Matcher m = Pattern.compile(regex).matcher(input);
if (! m.matches()) {
System.out.printf("%-41s\"%s\"%n", "No match", input);
} else {
String part1 = m.group(1);
String op1 = m.group(2);
String part2 = m.group(3);
String op2 = m.group(4);
String part3 = m.group(5);
long a = parse(null, part1);
long b = parse(op1, part2);
long c = parse((op2 != null ? op2 : op1), part3);
System.out.printf("%-6s%-6s%-6s%-6s%-6s%3d%3d%3d \"%s\"%n",
(part1 == null ? "" : '"' + part1 + '"'),
(op1 == null ? "" : '"' + op1 + '"'),
(part2 == null ? "" : '"' + part2 + '"'),
(op2 == null ? "" : '"' + op2 + '"'),
(part3 == null ? "" : '"' + part3 + '"'),
a, b, c, input);
}
}
private static long parse(String operator, String signedNumber) {
long number;
if (signedNumber == null)
number = 0;
else if (signedNumber.isEmpty())
number = 1;
else if (signedNumber.equals("-"))
number = -1;
else
number = Long.parseLong(signedNumber);
if ("-".equals(operator))
number = -number;
return number;
}
输出
part1 op1 part2 op2 part3 a b c input
"3" "+" "4" "+" "5" 3 4 5 "3x^2 + 4x + 5"
"" "+" "" "+" "1" 1 1 1 "x^2 + x + 1"
"" "-" "4" 1 -4 0 "x^2 - 4x"
"-" "-" "1" -1 0 -1 "-x^2 - 1"
"-4" "-" "5" 0 -4 -5 "-4x - 5"
"-3" -3 0 0 "-3x^2"
"-4" 0 -4 0 "-4x"
"-5" 0 0 -5 "-5"
No match ""
No match "-3x^2 + -1x"
答案 1 :(得分:1)
尝试一下:
((-?\d+)x\^2\s*[+-]\s*)?(\d+)x\s*([+-]\s*\d+)
(-?\d+)x\^2\s*[+-]\s*)?
-?\d+
-0或1个-
符号,后跟一个或多个数字x\^2
-x字符,^字符,2个字符\s*
-可选空间[+-]
-+字符或-字符?
-该组中的0或1。二次公式可能没有第一部分。删除此?
,使其不可选(\d+)x
-一个或多个数字,后跟x个字符(例如2x)\s*
-可选空间([+-]\s*\d+)
\s*
-可选空间\d+
-一个或多个数字(例如3)