【问题标题】:java regex split stringjava正则表达式拆分字符串
【发布时间】:2011-10-16 07:33:39
【问题描述】:

我有点难以想出用正则表达式来分解具有以下属性的字符串:

  1. 由 | 分隔(管道)字符
  2. 如果单个值包含管道,则使用 \(反斜杠)转义
  3. 如果单个值以反斜杠结尾,则使用反斜杠转义

例如,这里有一些我想分解的字符串:

  1. One|Two|Three 应该产生:["One", "Two", "Three"]
  2. One\|Two\|Three 应该产生:["One|Two|Three"]
  3. One\\|Two\|Three 应该产生:["One\", "Two|Three"]

现在我怎么能用一个正则表达式来拆分它?

更新:正如你们中的许多人已经建议的那样,这不是一个好的正则表达式应用程序。此外,正则表达式解决方案比仅迭代字符要慢几个数量级。我最终遍历了字符:

public static List<String> splitValues(String val) {
    final List<String> list = new ArrayList<String>();
    boolean esc = false;
    final StringBuilder sb = new StringBuilder(1024);
    final CharacterIterator it = new StringCharacterIterator(val);
    for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
        if(esc) {
            sb.append(c);
            esc = false;
        } else if(c == '\\') {
            esc = true;
        } else if(c == '|') {
            list.add(sb.toString());
            sb.delete(0, sb.length());
        } else {
            sb.append(c);
        }
    }
    if(sb.length() > 0) {
        list.add(sb.toString());
    }
    return list;
}

【问题讨论】:

  • 让我们说清楚。你想要的是这样的:分割|并将其从字符串中删除,不要用 \| 分割并从字符串中删除 \,最后由 \\| 分割并删除 \|从第一部分和 \ 从第二部分。你认为这可以用一个正则表达式来实现吗?在我看来,情况完全不同......
  • 是否可以更改分隔符?
  • 我认为你们是对的!这对于正则表达式来说可能太多了。

标签: java regex string split


【解决方案1】:

诀窍是不要使用split() 方法。这迫使您使用后向检测来检测转义字符,但是当转义本身被转义时(正如您所发现的那样),这将失败。您需要改用 find() 来匹配 tokens 而不是分隔符:

public static List<String> splitIt(String source)
{
  Pattern p = Pattern.compile("(?:[^|\\\\]|\\\\.)+");
  Matcher m = p.matcher(source);
  List<String> result = new ArrayList<String>();
  while (m.find())
  {
    result.add(m.group().replaceAll("\\\\(.)", "$1"));
  }
  return result;
}

public static void main(String[] args) throws Exception
{
  String[] test = { "One|Two|Three", 
                    "One\\|Two\\|Three", 
                    "One\\\\|Two\\|Three", 
                    "One\\\\\\|Two" };
  for (String s :test)
  {
    System.out.printf("%n%s%n%s%n", s, splitIt(s));
  }
}

输出:

One|Two|Three
[One, Two, Three]

One\|Two\|Three
[One|Two|Three]

One\\|Two\|Three
[One\, Two|Three]

One\\\|Two
[One\|Two]

【讨论】:

  • 这令人印象深刻。你能解释一下这个模式是如何工作的吗?我仍然在为正则表达式而苦恼。
  • 这就像一个魅力!再次感谢@艾伦摩尔!!现在你会如何做相反的事情?
  • @Paul:基本思想是你永远不会匹配反斜杠而不消耗下一个字符。这样你就永远不会与转义序列不同步。但如果你真的想了解正则表达式,你应该阅读The Book
猜你喜欢
  • 1970-01-01
  • 2021-06-17
  • 2011-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多