用java中的RegExparsingCSVinput
我知道,现在我有两个问题。 但我很开心!
我从这个build议开始,不要尝试和分裂,而是要匹配什么是可以接受的领域,并从这里扩展到这个expression。
final Pattern pattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?=,|$)");
表情看起来像这样没有恼人的逃脱引号:
"([^"]*)"|(?<=,|^)([^,]*)(?=,|$)
这对我来说很好,不pipe它是匹配“两个引号,还是它们之间的任何一个”,或者是“行首或逗号与行末或逗号之间的事情”。 迭代通过比赛获得我所有的领域,即使他们是空的。 例如,
the quick, "brown, fox jumps", over, "the",,"lazy dog"
分解成
the quick "brown, fox jumps" over "the" "lazy dog"
大! 现在我想放弃引号,所以我添加了前瞻性和隐藏的非捕获组,就像我为逗号所做的一样。
final Pattern pattern = Pattern.compile("(?<=\")([^\"]*)(?=\")|(?<=,|^)([^,]*)(?=,|$)");
再次expression的是:
(?<=")([^"]*)(?=")|(?<=,|^)([^,]*)(?=,|$)
而不是预期的结果
the quick brown, fox jumps over the lazy dog
现在我得到这个故障:
the quick "brown fox jumps" ,over, "the" ,, "lazy dog"
我错过了什么?
运算符优先级 基本上没有。 这一切都是从左到右。 所以or(|)适用于结束引用前瞻和逗号lookahead
尝试:
(?:(?<=")([^"]*)(?="))|(?<=,|^)([^,]*)(?=,|$)
当我开始明白我做错了什么的时候,我也开始明白这是怎么搞的。 我终于意识到,我不想要所有匹配的文本,我想要特定的组内。 我结束了使用一些非常类似于我的原始正则expression式,除了我没有看到closures逗号,我认为应该是更有效一点。 这是我的最终代码。
package regex.parser; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CSVParser { /* * This Pattern will match on either quoted text or text between commas, including * whitespace, and accounting for beginning and end of line. */ private final Pattern csvPattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)"); private ArrayList<String> allMatches = null; private Matcher matcher = null; private String match = null; private int size; public CSVParser() { allMatches = new ArrayList<String>(); matcher = null; match = null; } public String[] parse(String csvLine) { matcher = csvPattern.matcher(csvLine); allMatches.clear(); String match; while (matcher.find()) { match = matcher.group(1); if (match!=null) { allMatches.add(match); } else { allMatches.add(matcher.group(2)); } } size = allMatches.size(); if (size > 0) { return allMatches.toArray(new String[size]); } else { return new String[0]; } } public static void main(String[] args) { String lineinput = "the quick,\"brown, fox jumps\",over,\"the\",,\"lazy dog\""; CSVParser myCSV = new CSVParser(); System.out.println("Testing CSVParser with: \n " + lineinput); for (String s : myCSV.parse(lineinput)) { System.out.println(s); } } }
(?:^|,)\s*(?:(?:(?=")"([^"].*?)")|(?:(?!")(.*?)))(?=,|$)
这应该做你想要的。
说明:
(?:^|,)\s*
模式应该以string或string开始。 另外,在开始时忽略所有的空格。
先行一看,看看其余部分是否以报价开头
(?:(?=")"([^"].*?)")
如果是这样,那么不要贪婪地匹配,直到下一个报价。
(?:(?!")(.*?))
如果不是以引号开始,则不要贪婪地匹配,直到下一个逗号或string结束。
(?=,|$)
该模式应以逗号或string结尾结尾。
我知道这不是OP想要的,但是对于其他读者,可以使用String.replace方法之一去除OP当前正则expression式的结果数组中的每个元素的引号。