Java 正则表达式元字符在拆分时返回额外的 space
Java Regex Metacharacters returning extra space while spliting
我想使用正则表达式而不是 StringTokenizer 来拆分字符串。我正在使用 String.split(regex);
正则表达式包含元字符,当我使用 \[ 时,它在返回数组中返回额外的 space 。
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]
它returns数组长度为3并且
a m
Space前面也有一个。
任何人都可以解释为什么会发生这种情况以及我该如何纠正它。我不希望结果数组中有额外的 space。
由于[
在字符串的开头,当split
去掉[
时,第一次拆分后出现了两个元素:字符串的开头,以及字符串的其余部分。 String#split
不只 return 尾随 空元素(因为它默认使用 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
作为 , you may do the same without having to specify the pattern twice, by dealing with the 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
操作将始终 return 至少一个元素,即输入字符串,当没有匹配项时,即使字符串为空。如果您希望有一个空数组,那么唯一的解决方案是显式替换结果:
if(st.length==1 && s.equals[0]) st=new String[0];
或者,如果你只想特殊处理一个空字符串,你可以事先检查一下:
if(s.isEmpty()) st=new String[0];
else {
// the code as shown above
}
我想使用正则表达式而不是 StringTokenizer 来拆分字符串。我正在使用 String.split(regex); 正则表达式包含元字符,当我使用 \[ 时,它在返回数组中返回额外的 space 。
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]
它returns数组长度为3并且
a m
Space前面也有一个。 任何人都可以解释为什么会发生这种情况以及我该如何纠正它。我不希望结果数组中有额外的 space。
由于[
在字符串的开头,当split
去掉[
时,第一次拆分后出现了两个元素:字符串的开头,以及字符串的其余部分。 String#split
不只 return 尾随 空元素(因为它默认使用 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
作为 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
操作将始终 return 至少一个元素,即输入字符串,当没有匹配项时,即使字符串为空。如果您希望有一个空数组,那么唯一的解决方案是显式替换结果:
if(st.length==1 && s.equals[0]) st=new String[0];
或者,如果你只想特殊处理一个空字符串,你可以事先检查一下:
if(s.isEmpty()) st=new String[0];
else {
// the code as shown above
}