文件结构如下:
"group","type","scope","name","attribute","value"
"c","","Probes Count","Counter","value","35"
"b","ProbeInformation","Probes Count","Gauge","value","0"
始终使用引号。还有一个尾随换行符。
这是我所拥有的:
^(\"[^,\"]*\")(,(\"[^,\"]*\"))*(.(\"[^,\"]*\")(,(\"[^,\"]*\")))*.$
这不正确匹配。我正在使用 String.matches(regexp);
最佳答案
免责声明:我什至没有尝试编译我的代码,但这种模式以前曾有效过。
当我一眼看不出正则表达式的作用时,我会将其分成几行,这样更容易弄清楚发生了什么。不匹配的括号更加明显,您甚至可以添加注释。另外,让我们在它周围添加 Java 代码,以便避免奇怪的情况变得清晰。
^(\"[^,\"]*\")(,(\"[^,\"]*\"))*(.(\"[^,\"]*\")(,(\"[^,\"]*\")))*.$
变成了
String regex = "^" +
"(\"[^,\"]*\")" +
"(," +
"(\"[^,\"]*\")" +
")*" +
"(." +
"(\"[^,\"]*\")" +
"(," +
"(\"[^,\"]*\")" +
")" +
")*" +
".$";
好多了。现在开始正题:我看到的第一件事是引用值的正则表达式。它不允许在字符串中使用逗号 - 这可能不是您想要的 - 所以让我们解决这个问题。我们还将它放入自己的变量中,这样我们就不会在某些时候输入错误。最后,让我们添加注释,以便我们可以验证正则表达式正在做什么。
final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
String regex = "^" + // The beginning of the string
"(" + QUOTED_VALUE + ")" + // Capture the first value
"(," + // Start a group, a comma
"(" + QUOTED_VALUE + ")" + // Capture the next value
")*" + // Close the group. Allow zero or more of these
"(." + // Start a group, any character
"(" + QUOTED_VALUE + ")" + // Capture another value
"(," + // Started a nested group, a comma
"(" + QUOTED_VALUE + ")" + // Capture the next value
")" + // Close the nested group
")*" + // Close the group. Allow zero or more
".$"; // Any character, the end of the input
事情变得更加清晰了。我在这里看到两件大事:
1)(我认为)您正在尝试匹配输入字符串中的换行符。我会一起玩,但在换行符上分割输入比你正在做的更干净、更容易(不过这是一个你可以自己做的练习)。您还需要注意不同操作系统具有的不同换行符约定 ( read this )。
2) 你捕捉的太多了。您想要使用非捕获组,否则解析您的输出将会很困难且容易出错 ( read this )。
final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
final String NEWLINE = "(\n|\n\r|\r\n)"; // A newline for (almost) any OS: Windows, *NIX or Mac
String regex = "^" + // The beginning of the string
"(" + QUOTED_VALUE + ")" + // Capture the first value
"(?:," + // Start a group, a comma
"(" + QUOTED_VALUE + ")" + // Capture the next value
")*" + // Close the group. Allow zero or more of these
"(?:" + NEWLINE + // Start a group, any character
"(" + QUOTED_VALUE + ")" + // Capture another value
"(?:," + // Started a nested group, a comma
"(" + QUOTED_VALUE + ")" + // Capture the next value
")" + // Close the nested group
")*" + // Close the group. Allow zero or more
NEWLINE + "$"; // A trailing newline, the end of the input
从这里,我看到你又在重复工作。让我们解决这个问题。这还修复了原始正则表达式中缺少的 * 。看看能不能找到。
final String QUOTED_VALUE = "\"[^\"]*\""; // A double quote character, zero or more non-double quote characters, and another double quote
final String NEWLINE = "(\n|\n\r|\r\n)"; // A newline for (almost) any OS: Windows, *NIX or Mac
final String LINE = "(" + QUOTED_VALUE + ")" + // Capture the first value
"(?:," + // Start a group, a comma
"(" + QUOTED_VALUE + ")" + // Capture the next value
")*"; // Close the group. Allow zero or more of these
String regex = "^" + // The beginning of the string
LINE + // Read the first line, capture its values
"(?:" + NEWLINE + // Start a group for the remaining lines
LINE + // Read more lines, capture their values
")*" + // Close the group. Allow zero or more
NEWLINE + "$"; // A trailing newline, the end of the input
这更容易阅读,不是吗?现在,如果您的大讨厌的正则表达式不起作用,您可以对其进行分段测试。
您现在可以编译正则表达式,获取匹配器,并从中获取组。但您仍然有一些问题:
1) 我之前说过,换行符会更容易中断。原因之一是:如何确定每行有多少个值?硬编码它可以工作,但是一旦你的输入发生变化它就会崩溃。也许这对你来说不是问题,但这仍然是不好的做法。另一个原因:正则表达式对于我来说仍然太复杂。您确实可以通过 LINE 来逃脱惩罚。
2) CSV 文件允许这样的行:
"some text","123",456,"some more text"
要处理此问题,您可能需要添加另一个迷你正则表达式来获取带引号的值或数字列表。
关于java - 在Java中使用正则表达式验证csv文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13498701/