2016-01-20 40 views
1

我想使用正则表达式而不是StringTokenizer分割字符串。我正在使用String.split(正则表达式); 正则表达式包含元字符,当我使用\ [它在返回数组中返回额外的空间。Java Regex元字符在分割时返回额外空间

import java.util.Scanner; 
public class Solution{ 
    public static void main(String[] args) { 
     Scanner i= new Scanner(System.in); 
     String s= i.nextLine(); 
     String[] st=s.split("[!\\[,?\\._'@\\+\\]\\s\\\\]+"); 
     System.out.println(st.length); 
     for(String z:st) 
      System.out.println(z); 
     } 
} 

在i进入输入[a\m] 它返回数组长度为3和

a m 

空间也有一个前。 任何人都可以请解释为什么发生这种情况,我该如何纠正它。我不希望结果数组中有额外的空间。

+2

你的意思是有一个输入字符串'String s =“[a \\ m]”'? –

+1

因为你匹配'['和']':http://regexr.com/3ckg2 – MortenMoulder

+0

我在cmd处键入[a \ m],并且想要a和m作为输出 – Linkon

回答

3

由于[是在字符串的开始,当split除去[,出现在第一分割步骤之后两个元素:空字符串,它是在所述字符串的开头,并且该字符串的剩余部分。 String#split不返回尾随仅限空元素(因为它默认与limit=0一起执行)。

删除您从开始分割的字符(使用.replaceAll("^[!\\[,?._'@+\\]\\s\\\\]+",注意模式开头的^)。下面是一个示例代码,你可以利用:

String[] st="[a\\m]".replaceAll("^[!\\[,?._'@+\\]\\s\\\\]+", "") 
       .split("[!\\[,?._'@+\\]\\s\\\\]+"); 
System.out.println(st.length); 
for(String z:st) { 
    System.out.println(z); 
} 

demo

+0

非常感谢您的详细解释和代码:) – Linkon

+0

先生,如果我只输入!或者[它仍然返回1,而它应该返回0 :( – Linkon

+2

这是因为当你拆分一个空字符串时,你会得到1个空元素,使用[this code](http://ideone.com/4iHNHK)来处理 –

2

作为除了Wiktor Stribiżew’s answer,你可以做同样无需指定两次模式,通过直接处理的java.util.regex包。删除此冗余可避免潜在的错误,也可能是更有效的模式并不需要分析两次:

Pattern p = Pattern.compile("[!\\[,?\\._'@\\+\\]\\s\\\\]+"); 
Matcher m = p.matcher(s); 
if(m.lookingAt()) s=m.replaceFirst(""); 
String[] st = p.split(s); 
for(String z:st) 
    System.out.println(z); 

为了能够使用相同的模式,即无需使用锚^为删除前导分隔符,我们首先通过lookingAt()检查该格式是否真正匹配文本的开头,然后删除第一个匹配项。然后,我们继续执行split操作,但重新使用已准备好的Pattern


关于在留​​言中提到你的问题,split操作将始终返回至少一个元素,输入字符串,当没有比赛,即使字符串是空的。如果你想有一个空数组,那么,唯一的解决办法是明确替代结果:

if(st.length==1 && s.equals[0]) st=new String[0]; 

或者,如果你只想要特殊对待一个空字符串,你可以事先检查:

if(s.isEmpty()) st=new String[0]; 
else { 
    // the code as shown above 
} 
+0

非常感谢。你的代码也工作:) – Linkon