用逗号分隔外引号

我的程序从文件中读取一行。 这行包含逗号分隔的文本,如:

123,test,444,"don't split, this",more test,1 

我想分裂的结果是这样的:

 123 test 444 "don't split, this" more test 1 

如果我使用String.split(",") ,我会得到这个:

 123 test 444 "don't split this" more test 1 

换句话说:子串中的逗号"don't split, this"不是分隔符。 如何处理这个?

在此先感谢.. Jakob

你可以试试这个正则expression式:

 str.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); 

这将分割string,然后是偶数个双引号。 换句话说,它在双引号之外的逗号分割。 这将工作,只要你在你的string中有平衡的引号。

说明:

 , // Split on comma (?= // Followed by (?: // Start a non-capture group [^"]* // 0 or more non-quote characters " // 1 quote [^"]* // 0 or more non-quote characters " // 1 quote )* // 0 or more repetition of non-capture group (multiple of 2 quotes will be even) [^"]* // Finally 0 or more non-quotes $ // Till the end (This is necessary, else every comma will satisfy the condition) ) 

你甚至可以在代码中使用(?x)修饰符和你的正则expression式。 修饰符会忽略正则expression式中的任何空格,因此读取分成多行的正则expression式变得更容易:

 String[] arr = str.split("(?x) " + ", " + // Split on comma "(?= " + // Followed by " (?: " + // Start a non-capture group " [^\"]* " + // 0 or more non-quote characters " \" " + // 1 quote " [^\"]* " + // 0 or more non-quote characters " \" " + // 1 quote " )* " + // 0 or more repetition of non-capture group (multiple of 2 quotes will be even) " [^\"]* " + // Finally 0 or more non-quotes " $ " + // Till the end (This is necessary, else every comma will satisfy the condition) ") " // End look-ahead ); 

为什么分裂时,你可以匹配?

复活这个问题是因为某些原因,没有提到简单的解决scheme。 这里是我们精美紧凑的正则expression式:

 "[^"]*"|[^,]+ 

这将匹配所有想要的片段( 见演示 )。

说明

  • "[^"]*" ,我们匹配完整的"double-quoted strings"
  • |
  • 我们匹配[^,]+任何不是逗号的字符。

一个可能的改进是改进交替的string侧,以允许引用的string包括转义的引号。

你可以很容易地做到这一点,没有复杂的正则expression

  1. 分割字符" 。你得到一个string列表
  2. 处理列表中的每个string:将列表中的每个string拆分到列表中的一个偶数位置(从零开始索引)上(在列表中获得列表),将每个奇数位置的string单独放置(直接放入列表中的列表)。
  3. join列表,所以你只能得到一个列表。

如果你想处理'''的引用,你必须稍微调整algorithm(join一些部分,你错误地分割,或改变分裂为简单的正则expression式),但基本结构保持不变。

所以基本上是这样的:

 public class SplitTest { public static void main(String[] args) { final String splitMe="123,test,444,\"don't split, this\",more test,1"; final String[] splitByQuote=splitMe.split("\""); final String[][] splitByComma=new String[splitByQuote.length][]; for(int i=0;i<splitByQuote.length;i++) { String part=splitByQuote[i]; if (i % 2 == 0){ splitByComma[i]=part.split(","); }else{ splitByComma[i]=new String[1]; splitByComma[i][0]=part; } } for (String parts[] : splitByComma) { for (String part : parts) { System.out.println(part); } } } } 

这对于lambda来说会更清洁,承诺!

请参阅下面的代码片段。 这个代码只考虑开心stream量。 根据您的要求更改

 public static String[] splitWithEscape(final String str, char split, char escapeCharacter) { final List<String> list = new LinkedList<String>(); char[] cArr = str.toCharArray(); boolean isEscape = false; StringBuilder sb = new StringBuilder(); for (char c : cArr) { if (isEscape && c != escapeCharacter) { sb.append(c); } else if (c != split && c != escapeCharacter) { sb.append(c); } else if (c == escapeCharacter) { if (!isEscape) { isEscape = true; if (sb.length() > 0) { list.add(sb.toString()); sb = new StringBuilder(); } } else { isEscape = false; } } else if (c == split) { list.add(sb.toString()); sb = new StringBuilder(); } } if (sb.length() > 0) { list.add(sb.toString()); } String[] strArr = new String[list.size()]; return list.toArray(strArr); }