【问题标题】:Java Regex Metacharacters returning extra space while splitingJava 正则表达式元字符在拆分时返回额外的空间
【发布时间】:2016-04-26 17:47:37
【问题描述】:

我想使用正则表达式而不是 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  

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

【问题讨论】:

  • 你的意思是输入字符串String s="[a\\m]"
  • 因为你匹配[]regexr.com/3ckg2
  • 您只是将一个空字符串作为数组中的第一个元素,因为您的输入以 [ 开头,并且拆分也在 [ 上完成。
  • 从一开始就删除所有这些字符。 ideone.com/PXWLYg
  • 不,它不会删除 all,只会删除开头的那些。您对那些前导符号不感兴趣,因为它们会产生空数组元素,对吧?因此,仅在字符串开头删除它们是一种有效的方法。

标签: java regex java-8 metacharacters


【解决方案1】:

由于[在字符串的开头,当split删除[时,在第一个拆分步骤之后会出现两个元素:字符串开头的空字符串,其余的的字符串。 String#split 不只返回 trailing 空元素(因为它默认使用 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

【讨论】:

  • 非常感谢您的详细解释和代码:)
  • 先生,如果我只输入!或 [ 它仍然返回 1 而它应该返回 0 :(
  • 这是因为当你拆分一个空字符串时,你会得到1个空元素。使用this code 处理这种情况。
  • 从 Java 6 开始,您可以使用 string.isEmpty() 代替 string.length() != 0,但这只是风格上的区别……
  • 我在替换时使用 "\\\\" 而不是 "" 现在它返回 0
【解决方案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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2011-07-18
    相关资源
    最近更新 更多