5

我需要拆分包含基本数学表达式的字符串,例如:
"(a+b)*c"

" (a - c) / d"
分隔符是 + - * / ( ) 和空格,我需要它们作为独立的标记。基本上结果应该是这样的:

"("
"a"
"+"
"b"
")"
"*"
"c"

对于第二个例子:

" "
"("
"a"
" "
"-"
...

我阅读了很多关于使用不太复杂的分隔符的类似问题的问题,常见的答案是使用零空间正向前瞻和后向。
像这样:(?<=X | ?=X)
X 代表分隔符,但是将它们放在这样的类中:
[\\Q+-*()\\E/\\s]
不能以所需的方式工作。
那么我如何格式化分隔符以使拆分按我需要的方式工作?

---更新---
字类字符和较长的组合不应拆分。
如“ab”“c1”或“12”。
或者简而言之,我需要与 StringTokenizer 相同的结果,给出参数“-+*/()”和 true。

4

4 回答 4

1

如果您将其作为学生工作来做是一回事,但实际上这更像是词法分析器和解析器的工作。在 C 中,您将使用lexandyacc或 GNU flexand bison. 在 Java 中,您将使用ANTLRor JavaCC

但首先要为您的预期输入(通常称为输入语言)编写 BNF 语法。

于 2013-05-17T14:24:31.483 回答
1

尝试使用拆分数据

yourString.split("(?<=[\\Q+-*()\\E/\\s])|(?=[\\Q+-*()\\E/\\s])(?<!^)"));

我认为您遇到的问题不是\\Q+-*()\\E部分而是在(?<=X | ?=X)<- 它应该是(?<=X)|(?=X)因为它应该产生后视和前瞻。


演示"_a+(ab-c1__)+12_" (顺便说一句_,代码中的空格将被替换。所以将两个空格显示为一个,因此必须使用__以某种方式呈现它们)

String[] tokens = " a+(ab-c1  )+12 "
        .split("(?<=[\\Q+-*()\\E/\\s])|(?=[\\Q+-*()\\E/\\s])(?<!^)");
for (String token :  tokens)
    System.out.println("\"" + token + "\"");

结果

" "
"a"
"+"
"("
"ab"
"-"
"c1"
" "
" "
")"
"+"
"12"
" "
于 2013-05-17T14:28:26.120 回答
0

您可以使用以下正则表达式:

\s*(?<=[()+*/a-z-])\s*

?<=进行零宽度断言,即它们匹配,但不会在组中包含匹配的表达式。将\s*处理尾随空格。

代码示例:

String a = " (a - c) / d *       x   ";
String regex = "\\s*(?<=[()+*/a-z-])\\s*";
String[] split = a.split(regex);
System.out.println(Arrays.toString(split));

输出:

[ (, a, -, c, ), /, d, *, x]
于 2013-05-17T13:54:21.057 回答
0

试试这个:

[-+*()\\s]

破折号必须在字符类中排在首位或排在最后,以免表示范围。其余的字符不需要转义(大概是你试图用\\Qand做的事情\\E),因为大多数字符都是在字符类中按字面意思获取的。

另外,我不知道语法,(?<=X|?=X). 如果它有效,那就太好了。但如果没有,试试这个等价的扩展,我知道它的语法确实有效:

(?:(?<=X)|(?=X))
于 2013-05-17T13:53:37.427 回答