【问题标题】:Regular Expression for reading CSV in Java [duplicate]用于在 Java 中读取 CSV 的正则表达式 [重复]
【发布时间】:2012-10-26 21:46:46
【问题描述】:

可能重复:
Parsing CSV input with a RegEx in java

我有一个输入文件,其中每一行都有以下形式的字符串输入值:

   "  ab  cd  " ,    "  efgh,ijk.",  4,"lmno"

即,

  1. 这些词要么用引号引起来,要么没有引号。
  2. 开始和结束词前后的空格是不允许的。

编辑:3. 输入可以用逗号分隔。(abc,"Hi Mary,Joe",5)

在java中使用.Split(),我需要一个正则表达式来输出这个:

ab  cd
efgh,ijk.
4
lmno

我试过了:

[^",]*[\",]

但这不适用于"efgh,ijk."

这里是正则表达式测试的链接:http://regexpal.com/ 我需要一些帮助。请帮忙。 谢谢

【问题讨论】:

  • 那是CSV format。这种格式有 plenty of 解析器。你甚至可以很容易地write one自己。不要尝试将正则表达式用于非常规模式,它只会伤害你。
  • 5, ebo"eu ooeu" euoe, oeuou应该如何处理?
  • @durron597 - 这违反了 OP 关于输入外观的条件。值应该没有引号或被引号包围
  • @TedHopp 他的程序(如果要投入生产)应该处理非法输入。我的问题的答案可能是“抛出异常”
  • @BalusC - 在我看来就像一个正则表达式。怎么不呢?

标签: java regex split token


【解决方案1】:

DEMO

正则表达式模式:(?:\s*(?:\"([^\"]*)\"|([^,]+))\s*,?)+?

空值更新:(?:\s*(?:\"([^\"]*)\"|([^,]+))\s*,?|(?<=,)(),?)+?DEMO

它工作的一个例子,我知道它有点 CSV 格式,但只要你不写真的很奇怪的东西,它就会匹配所有的东西。

Matcher ma = Pattern.compile("(?:\\s*(?:\\\"([^\\\"]*)\\\"|([^,]+))\\s*,?)+?").matcher("   \"  ab  cd  \" ,    \"  efgh,ijk.\",  4,\"lmno\"");
while (ma.find()) {
    if (ma.group(1) == null) {
        System.out.println(ma.group(2));
    } else {
        System.out.println(ma.group(1));
    }
}

编辑,顺便说一句,如果您希望我们为您提供代码,请不要告诉我们有关正则表达式在线测试器的信息,如果您这样做是因为您知道如何处理正则表达式,如果您不知道该怎么做那个,也问吧。

【讨论】:

  • 这需要引号以及它后面的逗号。
  • 但是当我执行程序时它只打印空格和逗号
  • 因为你用null或\n替换它,我给你的是你需要的反向引用,你只需要循环并获取它们。
  • 你能告诉我怎么做吗?
  • 你得到了你的代码。
【解决方案2】:

尝试用(?:^\s*"\s*|\s*"\s*$|\s*"?\s*,\s*"?\s*) (demo) 调用split()

这也将匹配一个字符串中包含的逗号,这在您的情况下是错误的。但如果您要使用split(),这是唯一的方法。您可以引入一些转义包含的逗号的方法(如\,),这可以很容易地添加到正则表达式中。

否则,您将不得不使用其他方法来解析字符串,split() 不会帮助您。

【讨论】:

    【解决方案3】:

    如果您不想使用正则表达式,正则表达式意味着它是'regular' expression。 “我认为这里有一个模式”不是正则表达式。它们很好,速度很快,而且我只在完全控制输入正则表达式时才使用它们。

    //no development environment up, there may be compilation errors.
    private static String[] csv(final String input){
      String[] inputArray = input.split(",");
      for(int i =0;i < inputArray.length;i++){
    //org.apache.commons.lang.StringUtils
        String value = StringUtils.removeEnd(inputArray[i],"\"");
        value = StringUtils.removeStart(value,"\"");
        value = StringUtils.trim(value);
    
        inputArray[i] = value;
      }
      return inputArray;
    }
    

    【讨论】:

    • 您应该修剪两次字符串:在删除字符串末尾和开头的 " 之前和之后。
    • 如果字符串是 "a,b,c","def" 它将拆分为 a b c def。但我希望它是 a,b,c 和 def
    【解决方案4】:

    我建议找到匹配项,然后对其进行修剪以获得最终结果。

    Matcher m = Pattern.compile("\\s*(?:\"[^\"]*\"|(?:^|(?<=,))[^,]*)").matcher(s);
    while (m.find()) {
      System.out.println(m.group().replaceAll("^\\s*\"?\\s*(.*?)\\s*\"?\\s*$", "$1"));
    }
    

    this demo

    【讨论】:

      猜你喜欢
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      • 2014-05-13
      • 1970-01-01
      相关资源
      最近更新 更多