为了账号安全,请及时绑定邮箱和手机立即绑定

在双引号外的逗号上拆分。如果是单引号,则忽略双引号

在双引号外的逗号上拆分。如果是单引号,则忽略双引号

阿波罗的战车 2022-06-15 10:55:40
我有两种类型的字符串,我需要使用逗号分隔第一种(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(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)")它通过了第二个案例,但在第一个案例中失败了。请帮忙
查看完整描述

2 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

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

这意味着任何现有的通用 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 中的双引号是否应该是文字。它需要人类智能和领域知识来理解数据的含义。


查看完整回答
反对 回复 2022-06-15
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

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


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


查看完整回答
反对 回复 2022-06-15
  • 2 回答
  • 0 关注
  • 89 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信