Java 如何使用string#split分割带分隔符的字符串+;-*/()和空格,并将其作为额外标记保留?

Java 如何使用string#split分割带分隔符的字符串+;-*/()和空格,并将其作为额外标记保留?,java,regex,string,parsing,Java,Regex,String,Parsing,我需要拆分包含基本数学表达式的字符串,例如: “(a+b)*c” 或 “(a-c)/d” 分隔符是+-*/()和空格,我需要它们作为独立的标记。 基本上,结果应该如下所示: (“ “a” “+” “b” “”“ “*” “c” 第二个例子: ” (“ “a” ” “-” 我读了很多关于不太复杂的分隔符的类似问题,常见的答案是使用零空间正向前瞻和反向前瞻。 像这样:(?试试这个: [-+*()\\s] 破折号必须在字符类中位于第一位或最后一位,才能不表示范围。其余字符不需要转义(可能是您试图使

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


“(a-c)/d”

分隔符是+-*/()和空格,我需要它们作为独立的标记。 基本上,结果应该如下所示:

(“
“a”

“+”

“b”

“”“

“*”

“c”

第二个例子:


(“
“a”


“-”

我读了很多关于不太复杂的分隔符的类似问题,常见的答案是使用零空间正向前瞻和反向前瞻。
像这样:
(?试试这个:

[-+*()\\s]
破折号必须在字符类中位于第一位或最后一位,才能不表示范围。其余字符不需要转义(可能是您试图使用
\\Q
\\E
所做的),因为大多数字符都是在字符类中按字面意思提取的


另外,我不知道语法,
(?您可以使用以下正则表达式:

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

[ (, a, -, c, ), /, d, *, x]

如果你是学生,这是一件事,但实际上这更像是词法分析器和解析器的工作。在C语言中,你会使用
lex
yacc
或GNU
flex
bison
。在Java中,你会使用
ANTLR
JavaCC


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

尝试使用

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

" "
"a"
"+"
"("
"ab"
"-"
"c1"
" "
" "
")"
"+"
"12"
" "

a+ab-c1+12
应该如何分割?是
ab
一个标记还是一组
a*b
,这部分的结果应该是
a
*
b
?字符串中可能有数字吗?“ab”应该保留为“ab”以及“c1”和“12”
“a\uuuuuuuuuc”
(假设
是空格),内部的两个空格应产生一个
两个空格标记或两个
一个空格标记?我假设一个两个空格标记,因为
12
应该保留
12
,但只是想确定一下。它应该是两个一个空格标记(请也修复顶部的正则表达式)。@nhahdh(为了怀疑)我通常逃避一切,但在这种情况下,你的作品也一样。有了你的借口,我更新了答案。谢谢!我不知道逃避一切如何让事情变得更清楚,但我确实理解你为什么在怀疑的时候这么做。对我来说,当角色类中的大多数角色都被逃避时,更难跟踪它们。@nhahtdh it但是我完全同意你的观点。对不起,我忘了提到较长的词类字符组合应该保留在一个标记中。添加它。我将表达式更改为(?:(?除了你的答案)(?@thiemorkrause True,我之前用
(?)更新了我的答案=[\\Q+-*()\\E/\\s])(?(对不起,忘了通知你了)但是如果你喜欢
(?=(!^)[\\Q+-*()\\E/\\s])
也可以。
yourString.split("(?<=[\\Q+-*()\\E/\\s])|(?=[\\Q+-*()\\E/\\s])(?<!^)"));
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"
" "