当存在转义引号或括号外时,在逗号外部分割逗号

时间:2015-09-05 17:17:39

标签: java string split

是否可以使用以下条件拆分字符串?

  
      
  • 拆分,(即逗号)
  •   
  • 在每个元素上,忽略在第一个'和最后一个'
  • 中检查逗号   
  • 在每个元素上,忽略在第一个(和最后一个)中检查逗号
  •   

e.g。

String source = "to_char(DATE, 'YYYY,MM,DD'), 'I am sad :(', to_char(DATE, ('YYYY(MM,DD)')), to_char(DATE, ('YYYY,MM,DD)')), to_char(DATE, ('YYYY(MM,DD')), NAME, to_char(DATE, '(YYYY)MM,DD'), CITY || ', (UK)', CITY || ', US''s CITY', CITY || ', UK'";

String[] expected = new String[]{
"to_char(DATE, 'YYYY,MM,DD')", 
"'I am sad :('",
"to_char(DATE, ('YYYY(MM,DD)'))", // brackets within quotes within brackets
"to_char(DATE, ('YYYY,MM,DD)'))", // missing open bracket in quotes
"to_char(DATE, ('YYYY(MM,DD'))", // missing close bracket in quotes
"NAME", 
"to_char(DATE, '(YYYY)MM,DD')", 
"CITY || ', (UK)'", 
"CITY || ', US''s CITY'", // escape a single quote in quotes
"CITY || ', UK'"
};

String[] result = splitElements(source);
assert expected.equals(result);

前两个要点可以通过Splitting on comma outside quotes when escaped quotes exist

来实现

在使用SQL进行操作时,这非常有用。例如。拆分项目,追加,插入,添加项目等。

提前致谢。

2 个答案:

答案 0 :(得分:6)

我知道它有点长但相当直接,只需跟踪多少个parens以及内部或外部的引号。

String[] splitElements(String source) {
    int parencount = 0;
    boolean q = false;
    List<String> l = new ArrayList<>();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < source.length(); i++) {
        char c = source.charAt(i);
        switch (c) {
            case ',':
                if (!q && parencount == 0) {
                    l.add(sb.toString());
                    sb.setLength(0);
                } else {
                    sb.append(c);
                }
                break;

            case '(':
                if(!q) parencount++;
                sb.append(c);
                break;

            case ')':
                if(!q) parencount--;
                sb.append(c);
                break;

            case '\'':
                q = ! q;
                sb.append(c);
                break;

            default:
                sb.append(c);
                break;
        }
    }
    String last = sb.toString();
    l.add(last);
    String sa[] = l.toArray(new String[l.size()]);
    return sa;
}

答案 1 :(得分:1)

您可以使用java String的{​​{3}}方法和

来完成此操作

<强>正则表达式:

(?<!\([^\(\)']{0,100}),(?![^\(\)']*\))(?=(?:'[^']*'|[^'])*$)

<强>解释

(?<!\([^\(\)']{0,100}),(?![^\(\)']*\))

,未被(...)包围的任何{0,100},请注意,在此我需要使用有限量词,我任意使用(?=(?:'[^']*'|[^'])*$)

'

使用预测来保证偶数个,(?:'[^']*')*$计数直到字符串结尾(正则表达式:')或者存在由任意组成的字符串除[^']*$之外的字符,直到字符串结尾(正则表达式:,)。

<强>策略

  1. 使用否定前瞻,负面反馈以确保(...)超出'
  2. 使用前瞻来保证前面只有,对,从public class Main{ public static void main(String[] args) { String source = "to_char(DATE, 'YYYY,MM,DD'), to_char(DATE, ('YYYY(MM,DD)')), " + "to_char(DATE, ('YYYY,MM,DD)')), to_char(DATE, ('YYYY(MM,DD')), " + "NAME, to_char(DATE, '(YYYY)MM,DD'), CITY || ', (UK)', " + "CITY || ', US''s CITY', CITY || ', UK', " + "'I am sad :(', to_char(DATE, 'YYYY,MM,DD')"; String delimiters = "(?<!\\([^\\(\\)']{0,100}),(?![^\\(\\)']*\\))(?=(?:'[^']*'|[^'])*$)"; String[] tokens = source.split(delimiters); for(String token : tokens) { System.out.println(token.trim()); } } } 到字符串结尾。
  3. 代码示例:

    to_char(DATE, 'YYYY,MM,DD')
    to_char(DATE, ('YYYY(MM,DD)'))
    to_char(DATE, ('YYYY,MM,DD)'))
    to_char(DATE, ('YYYY(MM,DD'))
    NAME
    to_char(DATE, '(YYYY)MM,DD')
    CITY || ', (UK)'
    CITY || ', US''s CITY'
    CITY || ', UK'
    'I am sad :('
    to_char(DATE, 'YYYY,MM,DD')
    

    <强>输出:

    -i