Regular Express用于忽略仅限空格的令牌

时间:2015-06-04 07:22:34

标签: java regex

我不是正则表达的专家,想知道是否有人可以在这里帮助我:

我想分割以下字符串:

04/16/2015 14:01:58.819   (27327) [ERR] [SYSTEM CALL]  SOCKET BIND port=4664: Address already in use [tsocket:820]

进入以下5个令牌:

04/16/2015 14:01:58.819
27327
ERR
SYSTEM CALL
SOCKET BIND port=4664: Address already in use [tsocket:820]

以下Java代码使用正则表达式[()\\[\\]]为我做,但它效率低

List<String> splitline(String line) {
    List<String> tokens = new ArrayList<>();
    int numToks = 0;
    line = line.trim();
    //Question 1: Change regular expression to remove white-space-only tokens!!
    String[] rawToks = line.split("[()\\[\\]]");
    for (String t : rawToks) {
        String token = t.trim();
        if (!token.isEmpty()) {
            if (numToks < 4) {
                tokens.add(token);
            }
            numToks++;
        }
    }
    //Question 2: Can the regular express be enhanced to eliminate this step?
    //In case the last required token contains () or [] then there will be more than 5 tokens,
    //so split by the 4th token (with [] around it) & use the 2nd token from the result
    if (numToks > 4) {
        tokens.add(line.split("\\[" + tokens.get(3) + "\\]")[1].trim());
    }
    return tokens;
}

有没有人对上面代码中嵌入的2个问题有答案?

修改

以下代码回答了上述两个问题,感谢下面接受的答案!

List<String> splitline(String line) {
    return Arrays.asList(line.trim().split("[)\\]]?\\s+[(\\[]|]\\s+", 5)); 
}

4 个答案:

答案 0 :(得分:1)

\\s*[()\\[\\]]\\s*

您可以简单地拆分并使用not Nonenot empty删除空的拆分部分,无论java.See演示中有哪些。

https://regex101.com/r/nS2lT4/6

答案 1 :(得分:0)

根据以下正则表达式分割字符串。

string.split("\\s*[(\\[)\\]]\\s*");

这会与[]()符号以及前面或后面的可选空格分开。

答案 2 :(得分:0)

它看起来像一个非常标准的行格式,每行将具有相似的格式,并且将是5个令牌。

如果是这种情况,使用split并不是一个好主意。为什么不简单地使用捕获组并获取该5组的内容?

String input = "04/16/2015 14:01:58.819   (27327) [ERR] [SYSTEM CALL]  SOCKET BIND port=4664: Address already in use [tsocket:820]";
Pattern p = Pattern.compile("^(.*) *\\((\\d*)\\) \\[(.*?)\\] \\[(.*?)\\] *(.*)$");
Matcher m = p.matcher(input);
System.out.println("matches? " + m.matches());
for (int i = 0; i < m.groupCount(); i++) {
    System.out.println(m.group(i+1));
}

答案 3 :(得分:0)

我建议如下:

return Arrays.asList(line.split("[)\\]]?\\s+[(\\[]|]\\s+"));

说明:

这个正则表达式匹配两种可能性之一:

  1. 可选的右括号/括号,后跟空格,后跟左括号/括号。
  2. 结束括号后跟空格。
  3. 第一个选项匹配字符串中的以下内容:

    04/16/2015 14:01:58.819   (27327) [ERR] [SYSTEM CALL]  SOCKET BIND port=4664: Address already in use
                           ^^^^     ^^^   ^^^
    

    第二个选项匹配“SYSTEM CALL”之后的部分。

    这意味着该行将被分割为而没有任何空标记

    修改

    为避免在您的上一个字段中匹配括号/括号,当您知道您只想分隔5个字段时,只需将上述内容更改为:

    return Arrays.asList(line.split("[)\\]]?\\s+[(\\[]|]\\s+",5));
    

    String.split(String regex, int limit)String.split()的一个版本,不会超出limit令牌。也就是说,即使最后一个令牌包含潜在匹配,也不会对其进行测试,并且整个剩余字符串将位于第五个令牌中。