1

我想从 CSV(逗号分隔)文件中解析一行,如下所示:

Bosh,Mark,mark@gmail.com,"3, Institute","83, 1, 2",1,21

我必须解析文件,而不是我想要的撇号之间的逗号';',就像这样:

Bosh,Mark,mark@gmail.com,"3; Institute","83; 1; 2",1,21

我使用以下 Java 代码,但它不能很好地解析它:

Pattern regex = Pattern.compile("(\"[^\\]]*\")");
        Matcher matcher = regex.matcher(line);
        if (matcher.find()) {
            String replacedMatch = matcher.group();
            String gr1 = matcher.group(1);
            gr1.trim();
            replacedMatch = replacedMatch.replace(",", ";");
            line = line.replace(matcher.group(), replacedMatch);
        }

输出是:

Bosh,Mark,mark@gmail.com,"3; Institute";"83; 1; 2",1,21

有人知道如何解决这个问题吗?

4

6 回答 6

3

这是我将,内部引号替换为;. 它假定如果"要出现在带引号的字符串中,那么它会被另一个". 此属性确保从开始计数到当前字符,如果引号数"为奇数,则该字符位于带引号的字符串内。

// Test string, with the tricky case """", which resolves to
// a length 1 string of single quote "
String line = "Bosh,\"\"\"\",mark@gmail.com,\"3, Institute\",\"83, 1, 2\",1,21";

Pattern pattern = Pattern.compile("\"[^\"]*\"");
Matcher matcher = pattern.matcher(line);

int start = 0;

StringBuilder output = new StringBuilder();

while (matcher.find()) {
  // System.out.println(m.group() + "\n " + m.start() + " " + m.end());
  output
    .append(line.substring(start, matcher.start())) // Append unrelated contents
    .append(matcher.group().replaceAll(",", ";")); // Append replaced string

  start = matcher.end();
}
output.append(line.substring(start)); // Append the rest of unrelated contents

// System.out.println(output);

虽然我找不到任何会像您在 中那样替换匹配组的方法失败的情况,但line = line.replace(matcher.group(), replacedMatch);我觉得从头开始重建字符串更安全。

于 2012-06-29T10:23:45.380 回答
2

这里有一个方法:

import java.util.regex.*;

class Main {

  public static void main(String[] args) {

    String in = "Bosh,Mark,mark@gmail.com,\"3, \"\" Institute\",\"83, 1, 2\",1,21";
    String regex = "[^,\"\r\n]+|\"(\"\"|[^\"])*\"";
    Matcher matcher = Pattern.compile(regex).matcher(in);
    StringBuilder out = new StringBuilder();

    while(matcher.find()) {
      out.append(matcher.group().replace(',', ';')).append(',');
    }

    out.deleteCharAt(out.length() - 1);
    System.out.println(in + "\n" + out);
  }
}

这将打印:

Bosh,Mark,mark@gmail.com,"3,""研究所","83,1,2",1,21
Bosh,Mark,mark@gmail.com,"3;""研究所","83;1;2",1,21

在 Ideone 上测试:http: //ideone.com/fCgh7

于 2012-06-29T10:54:23.167 回答
1

这是你需要的

String line = "Bosh,Mark,mark@gmail.com,\"3, Institute\",\"83, 1, 2\",1,21";
    Pattern regex = Pattern.compile("(\"[^\"]*\")");
    Matcher matcher = regex.matcher(line);
    while(matcher.find()){
        String replacedMatch = matcher.group();
        String gr1 = matcher.group(1);
        gr1.trim();
        replacedMatch = replacedMatch.replace(",", ";");
        line = line.replace(matcher.group(), replacedMatch);
    }

行将具有您需要的价值。

于 2012-06-29T10:21:40.307 回答
0

你试过让 RegExp 变得懒惰吗?另一个想法:在 [] 内你也应该使用 "。如果你这样做,你应该有预期的输出并设置了全局标志。

于 2012-06-29T09:59:26.600 回答
0

你的正则表达式有问题。为什么要确保“...”表达式中没有 ]?你宁愿让正则表达式不情愿(默认是急切的,这意味着它会尽可能多地捕获)。

"(\"[^\\]]*\")"

应该

"(\"[^\"]*\")"

但是 nhadtdh 是对的,您应该使用适当的 CSV 库来解析它并将 , 替换为 ; 在解析器返回的值中。我相信你在谷歌搜索“Java CSV 解析器”时会找到一个解析器。

于 2012-06-29T10:01:55.727 回答
0

你的正则表达式不应该是 ("[^"]*") 吗?换句话说,你的第一行应该是:

Pattern regex = Pattern.compile("(\"[^\"]*\")");

当然,这是假设您的输入行的引用值中不能有引号。

于 2012-06-29T10:12:17.243 回答