1

我想使用正则表达式而不是 StringTokenizer 来拆分字符串。我正在使用 String.split(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);
        }
}

当我输入输入时[a\m] ,它返回数组长度为 3 和

 a m  

空间也在前一个。谁能解释为什么会发生这种情况以及我该如何纠正它。我不希望结果数组中有额外的空间。

4

2 回答 2

3

由于[是字符串的开头,当splitremoves时[,在第一个拆分步骤之后会出现两个元素:字符串开头的空字符串和字符串的其余部分。String#split不只返回尾随的空元素(因为它limit=0默认执行)。

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

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

演示

于 2016-01-20T18:28:34.757 回答
2

作为对Wiktor Stribiżew 的回答的补充,您可以直接处理包来执行相同操作,而无需两次指定模式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
}
于 2016-01-20T19:24:42.750 回答