为什么我在Java String.split(regex)中有空标记?

时间:2014-04-10 13:36:55

标签: java regex

我是正则表达式的新手,我正在尝试用它来解析用“(”,“)”和空格分隔的标记。这是我的尝试:

String str = "(test (_bit1 _bit2 |bit3::&92;test#4|))";
String[] tokens = str.split("[\\s*[()]]"); 
for(int i = 0; i < tokens.length; i++)
  System.out.println(i + " : " + tokens[i]);

我期待以下输出:

  

0:测试
    1:_bit1
    2:_bit2
    3:| bit3 ::&amp; 92; test#4 |

但是,实际输出中会出现两个空标记:

  

0:
    1:测试
    2:
    3:_bit1
    4:_bit2
    5:| bit3 ::&amp; 92;测试#4 |

我不明白为什么我在0和2位置有两个空标记。有人能给我一个提示吗?谢谢。

=====更新====

Alan Moore的答案删除了它。但我喜欢这个答案,所以我把它复制在这里供我自己参考。

  

你的正则表达式,[\ s * [()]]匹配一个空格字符(\ s)或其中一个   字符*,(,或)。在开头的分隔符   string(()是你获得空的第一个令牌的原因。没有办法解决   那;你只需要检查一个空的第一个令牌并忽略它。

     

第二个空标记位于第一个空格和(第二个空格)之间   跟着它。那是你的,因为你使用了*(零或更多)   而不是+(一个或多个)。但修复它并不是那么简单。你要   在空间,parens或两者上分开,但你必须确保有   至少一个角色,无论哪个角色。这可能会这样做:

     

\ S * [()] + \ S * | \ S +

     

但你可能也应该在parens之间留出空格:

     

\ S *(?:[()] + \ S *)+ | \ S +

     

作为Java字符串文字,即:

     

\ S *(?:[()] + \ S *)+ | \ S +

4 个答案:

答案 0 :(得分:3)

你的正则表达式错了,试试这个:

String [] tokens = str.split(&#34; [\ s(\)] +&#34;);

String[] tokens = str.split("[\\s()]+"); //At least one character

更新:我注意到你的代码实际上删除了括号,所以看起来你不必在括号之间转义它们......不知道为什么,任何人都可以回答这个问题?

新更新:感谢@AlanMoore的解释,因为我了解[]中的括号并不需要转义。

答案 1 :(得分:2)

我的建议是,首先从两端删除分裂字符(以避免空字符串),然后进行分割。

String[] tokens = str.replaceAll("^[\\s()]+|[\\s()]+$", "").split("[\\s()]+"); 
                           -- replace leading or trailing--

另外,我已将您的分割字符(空格,( ))放在字符类[]

答案 2 :(得分:1)

您遇到的问题是它仍然在分隔符之间创建一个空字符串,然后在它到达分隔符后返回它。

您可以通过添加额外内容来了解​​我正在谈论的内容(例如:

String str = "(test (_bit1 (_bit2 |bit3::&92;test#4|))";

输出将变为:

0 : 
1 : test
2 : 
3 : _bit1
4 : 
5 : _bit2
6 : |bit3::&92;test#4|

我建议使用以下代码:

String str = "(test (_bit1 (_bit2 |bit3::&92;test#4|))";
String[] tokensArray = str.split("[\\s[()]*]");
ArrayList<String> tokens = new ArrayList<>();
for (String token : tokensArray) {
    if (!token.isEmpty()) {
        tokens.add(token);
    }
}
for (int i = 0; i < tokens.size(); i++)
    System.out.println(i + " : " + tokens.get(i));

这样做是从阵列中删除任何空标记,因为这些标记被认为是“不正确”的标记。

答案 3 :(得分:0)

索引0是第一个(之前的标记。索引2是空格与输入字符串中第二个(之间的标记。

我认为你不能避开第一个,但你可以使用

来抑制第二个
str.split("[\\s()]+");