我想分割以下字符串:
String line ="DOB,1234567890,11,07/05/12,\"first,last\",100,\"is,a,good,boy\"";
以下代币:
DOB
1234567890
11
07/05/12
first,last
100
is,a,good,boy
我尝试使用以下正则表达式:
import java.util.*;
import java.lang.*;
import java.util.regex.*;
import org.apache.commons.lang.StringUtils;
class SplitString{
public static final String quotes = "\".[[((a-z)|(A-Z))]+( ((a-z)|(A-Z)).,)*.((a-z)|(A-Z))].\"" ;
public static final String ISSUE_UPLOAD_FILE_PATTERN = "((a-z)|(A-Z))+ [(((a-z)|(A-Z)).,)* + ("+quotes+".,) ].((a-z)|(A-Z)) + ("+quotes+")";
public static void main(String[] args){
String line ="DOB,1234567890,11,07/05/12,\"first,last\",100,\"is,a,good,boy\"";
String delimiter = ",";
Pattern p = Pattern.compile(ISSUE_UPLOAD_FILE_PATTERN);
Pattern pattern = Pattern.compile(ISSUE_UPLOAD_FILE_PATTERN);
String[] output = pattern.split(line);
System.out.println(" pattern: "+pattern);
for(String a:output){
System.out.println(" output: "+a);
}
}
}
我在正则表达式中遗漏了什么吗?
答案 0 :(得分:1)
这是代码的更新版本,可为您提供预期的输出:
public static final String ISSUE_UPLOAD_FILE_PATTERN = "(?<=(^|,))(([^\",]+)|\"([^\"]*)\")(?=($|,))";
public static void main(String[] args) {
String line = "DOB,1234567890,11,07/05/12,\"first,last\",100,\"is,a,good,boy\"";
Matcher matcher = Pattern.compile(ISSUE_UPLOAD_FILE_PATTERN).matcher(line);
while (matcher.find()) {
if (matcher.group(3) != null) {
System.out.println(matcher.group(3));
} else {
System.out.println(matcher.group(4));
}
}
}
正则表达式的工作原理如下:
(?<=(^|,))
:检查匹配前的字符是字符串的开头还是,
(([^\",]+)|\"([^\"]*)\")
:匹配"<any number of (not")>"
或any number of (not" or ,)
(?=($|,))
:检查匹配后的字符是否为字符串结尾或,
结果将是第3组或第4组,具体取决于匹配的部分。
答案 1 :(得分:0)
您的正则表达式会对[
和]
执行一些奇怪的操作:使用这些内容并不像字符范围那样。出于这个原因,我没有打扰decypher并修复你的所有表达。
作为第二个注释,您应该确定正则表达式应该描述的内容:您希望它们与令牌之间的分隔符匹配,还是每个个别非分隔符令牌?使用split方法意味着前者,但我想对于您的应用程序,后者更容易实现。实际上在recent answer of mine中,我想出了一个匹配csv文件标记的正则表达式:
String tokenPattern = "\"[^\"]*(\"\"[^\"]*)*\"|[^,]*";
这将匹配
您可以使用此功能,为您的线路创建匹配器,使用find
迭代所有匹配并使用group()
提取令牌。如果您需要列的语义值,您可以使用该循环来删除引号并将双引号转换为单引号。
作为替代方案,您当然也可以根据问题的评论中的建议使用CSV阅读器。