【问题标题】:Splitting on comma outside pair of double quotes . Ignore double quotes if it is single在双引号外的逗号上拆分。如果是单引号,则忽略双引号
【发布时间】:2019-07-05 17:00:49
【问题描述】:

我有两种类型的字符串需要用逗号分隔

第一种类型(1" 表示 1 英寸)

130,TEXT 1" 67 SERIES ,400,4,1,998,.010,9,-,7,130

第二种类型

130,"TEXT, SAMPLE TEXT",400,4,1,998,.010,9,-,7,130

在第一种类型中,我需要按原样获取字符串并使用 , 所以我的分割值为 130 和 TEXT 1" 67 SERIES 等等。

但在第二种类型中,我需要忽略双引号之间的逗号并将字符串作为一个整体。

我用这个分开

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

它通过了第二种情况但在第一种情况下失败了。请帮忙

【问题讨论】:

  • 您可以使用csv 解析器。

标签: java regex string csv split


【解决方案1】:

您的输入格式不是有效的 CSV 格式。根据 Wikipedia Comma-separated values 页面,如果完全使用引号,则必须引用字段 中的文字引号字符。

这意味着任何现有的通用 CSV 解析器库都不太可能同时处理同一文件中的两种类型的行。

为了说明这个问题有多深,请考虑:

   130,TEXT 1" 67 SERIES, TEXT 2",4,1,998,.010,9,-,7,130

这可能意味着:

  • 一个字段包含TEXT 1" 67 SERIES, TEXT 2"
  • 一个字段包含TEXT 1 67 SERIES, TEXT 2,或
  • 两个字段TEXT 1" 67 SERIESTEXT 2"

消除歧义的唯一方法是编写一些自定义逻辑以对其进行分类......基于您自己的业务规则。

我认为你不能用split 和正则表达式来做到这一点。您需要编写一个适当的自定义解析器。

但在这种情况下,我认为您有权反对创建此 CSV 数据的任何人/任何人。他们应该遵守规则。我很想实现我的系统,通过现成的语法检查器提供 CSV 文件,并自动拒绝任何未通过验证的文件。

你能修复自动引用的错误吗?我认为不是……在一般情况下。如前所述,无法判断格式错误的 CSV 中的双引号是否应该是文字。它需要人类智能和领域知识来理解数据的含义。

【讨论】:

  • 是的,该文件来自旧系统,我们无法更改它。处理所有极端情况的自定义解析逻辑。
  • 即使是旧系统也可以更改。
  • 我无法控制那些 .所以无法更改。无论我收到什么,我都必须处理
【解决方案2】:

不知道如何(如果有的话)使用单个正则表达式来完成。但这是一种蛮力方法,它计算字符串中引号的数量并从那里开始。

public static void main(String[] args) {
    System.out.println("---Type 1---");
    for (String s : split("130,TEXT 1\" 67 SERIES ,400,4,1,998,.010,9,-,7,130")) {
        System.out.println(s);
    }
    System.out.println("\n---Type 2---");
    for (String s : split("130,\"TEXT, SAMPLE TEXT\",400,4,1,998,.010,9,-,7,130")) {
        System.out.println(s);
    }
}

private static List<String> split(String str) {
    List<String> tokens = new ArrayList<>();
    if (str.split("\"").length > 2) {
        int firstQuoteIndex = str.indexOf("\"");
        int secondQuoteIndex = str.indexOf("\"", firstQuoteIndex + 1);
        tokens.add(str.substring(0, firstQuoteIndex - 1));
        tokens.add(str.substring(firstQuoteIndex + 1, secondQuoteIndex));
        tokens.addAll(Arrays.asList(str.substring(secondQuoteIndex + 2).split(",")));
    } else {
        tokens.addAll(Arrays.asList(str.split(",")));
    }
    return tokens;
}

输出

---Type 1---
130
TEXT 1" 67 SERIES 
400
4
1
998
.010
9
-
7
130

---Type 2---
130
TEXT, SAMPLE TEXT
400
4
1
998
.010
9
-
7
130

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 1970-01-01
    • 2011-12-25
    • 2017-08-08
    • 2016-03-19
    • 1970-01-01
    相关资源
    最近更新 更多