[英]Java: splitting a semicolon separated string but ignoring escape+semicolon in quotes
我想拆分我的查询,但没有得到完全符合我要求的答案。
我的字符串如下所示:
选择 1;选择 \\\\2; select 3\\\\;copy customer from 's3://mybucket/mydata' 凭证 'aws_access_key_id=access_key\\\\;aws_secret_access_key=secret_key\\\\;master_symmetric_key=master_key'
所需的输出:
选择 1
选择 \\\\2
选择 3\\\\
从 's3://mybucket/mydata' 凭证复制客户 'aws_access_key_id=access_key\\\\;aws_secret_access_key=secret_key\\\\;master_symmetric_key=master_key'
我找到了关于逃生者的解决方案。 但是不符合我的要求。
(?<!\\\\);
在 Java String.split() 方法中处理带有转义字符的分隔符
如何忽略引号中的转义+分号?
帮我。
我认为这是一个解决方案:
String line = "select 1;select \\2; select 3\\;copy customer from 's3://mybucket/mydata' credentials 'aws_access_key_id=access_key\\;aws_secret_access_key=secret_key\\;master_symmetric_key=master_key'";
line = line.replace("\\","\\\\");//To avoid missing \
String[] tokens = line.split(";(?=([^']*'[^']*')*[^']*$)");//To split on semmicolons, but not those inside quotes
for(String t : tokens) {
System.out.println("> "+t);
}
你可以在这里测试它http://rextester.com/MLTA75734
您可以使用外部 .jar 文件,例如 commons-lang-2.6.jar
String str = "select 1;select \\2; select 3\\;copy customer from 's3://mybucket/mydata' credentials 'aws_access_key_id=access_key\\;"
+ "aws_secret_access_key=secret_key\\;"
+ "master_symmetric_key=master_key'";
str = StringEscapeUtils.escapeJavaScript(str); // method from external jar
String st[] = str.split(";");
for(int i=0;i<st.length;i++)
System.out.println(st[i]);
希望能帮到你...
我尝试了另一种解决方案,这次没有正则表达式。 我用我能想到的尽可能多的奇怪字符串检查了这个,它按我的预期工作(希望这次它也能按你的预期工作),请检查一下。
String s ="select 1;r;select \\2; select 3\\;copy customer from 's3://mybucket/mydata' credentials 'aws_access_key_id=<access-key-id>\\;aws_secret_access_key=<secret-access-key>\\;master_symmetric_key=<master-key>'";
//"select 1;r;select \\2; select 3\\;copy customer from 'r;s3://mybucket/mydata;r' credentials 'a_key;b_key;c_key\\;r' 'aws_access_key_id=access_key\\;aws_secret_access_key=secret_key\\;master_symmetric_key=master_key'";
s = s.replace("\\","\\\\");
List<String> tokens = new ArrayList<String>();
int i = 0;
int j = 0;
String backup = s;
while (i < s.length()){
char c = s.charAt(i);
if(c==';'){
String previous = s.substring(0,i);
int quotesBefore = StringUtils.countMatches(backup.substring(0,j), "'");
if(i<2 || quotesBefore==0 || (i>1 && (quotesBefore & 1) == 0 || ((quotesBefore & 1) != 0) && !(s.charAt(i-1)=='\\' && s.charAt(i-2)=='\\'))){//Even quotes before OR (odd quotes AND not \\ right before)
tokens.add(previous);
if(i>0)s=s.substring(i+1);
i=0;
}
}
i++;j++;
}
tokens.add(s);
for(String t : tokens) {
System.out.println("> "+t);
}
基本步骤:
迭代字符串字符
对于每个检查它是否是分号
我使用了以下解决方案,用于带引号(' 和“)和转义(\\)字符的通用 sting 拆分器。
public static List<String> split(String str, final char splitChar) {
List<String> queries = new ArrayList<>();
int length = str.length();
int start = 0, current = 0;
char ch, quoteChar;
while (current < length) {
ch=str.charAt(current);
// Handle escape char by skipping next char
if(ch == '\\') {
current++;
}else if(ch == '\'' || ch=='"'){ // Handle quoted values
quoteChar = ch;
current++;
while(current < length) {
ch = str.charAt(current);
// Handle escape char by skipping next char
if (ch == '\\') {
current++;
} else if (ch == quoteChar) {
break;
}
current++;
}
}else if(ch == splitChar) { // Split sting
queries.add(str.substring(start, current + 1));
start = current + 1;
}
current++;
}
// Add last value
if (start < current) {
queries.add(str.substring(start));
}
return queries;
}
public static void main(String[] args) {
String str = "select 1;select \\\\2; select 3\\\\;copy customer from 's3://mybucket/mydata' credentials 'aws_access_key_id=access_key\\\\;aws_secret_access_key=secret_key\\\\;master_symmetric_key=master_key'";
List<String> queries = split(str, ';');
System.out.println("Size: "+queries.size());
for (String query : queries) {
System.out.println(query);
}
}
得到结果
Size: 4
select 1;
select \\2;
select 3\\;
copy customer from 's3://mybucket/mydata' credentials 'aws_access_key_id=access_key\\;aws_secret_access_key=secret_key\\;master_symmetric_key=master_key'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.