在 Java 中,如何标记包含标记中分隔符的字符串?

In Java, how do you tokenize a string that contains the delimiter in the tokens?

假设我有字符串:

String toTokenize = "prop1=value1;prop2=String test='1234';int i=4;;prop3=value3";

我想要代币:

  1. prop1=value1
  2. prop2=字符串测试='1234';int i=4;
  3. prop3=value3

为了向后兼容,我必须使用分号作为分隔符。我试过用类似 CDATA:

的方式包装代码
String toTokenize = "prop1=value1;prop2=<![CDATA[String test='1234';int i=4;]]>;prop3=value3";

但是我想不出一个正则表达式来忽略 cdata 标签中的分号。

我试过转义非定界符:

String toTokenize = "prop1=value1;prop2=String test='1234'\;int i=4\;;prop3=value3";

但是删除转义字符时会出现一团乱麻。

你有什么建议吗?

先决条件:

  • 您所有的标记都以 prop

  • 开头
  • 除了token的开头,文件中没有prop

我只是将所有 ;prop 替换为 ~prop

然后你的字符串变成:

"prop1=value1~prop2=String test='1234';int i=4~prop3=value3";

然后您可以使用 ~ 分隔符

进行分词

您可以匹配 <![CDATA...]]>; 以外的任何字符 1 次或多次,以匹配值。要匹配键,您可以使用常规 \w+ 模式:

(\w+)=((?:<!\[CDATA\[.*?]]>|[^;])+)

参见regex demo

详情

  • (\w+) - 第 1 组:一个或多个单词字符
  • = - = 符号
  • ((?:<!\[CDATA\[.*?]]>|[^;])+) - 第 1 组:一个或多个序列
    • <!\[CDATA\[.*?]]> - <![CDATA[...]]> 子串
    • | - 或
    • [^;] - 除了 ;
    • 之外的任何字符

看到一个Java demo:

String rx = "(\w+)=((?:<!\[CDATA\[.*?]]>|[^;])+)";
String s = "prop1=value1;prop2=<![CDATA[String test='1234';int i=4;]]>;prop3=value3";
Pattern pattern = Pattern.compile(rx);
Matcher matcher = pattern.matcher(s);
while (matcher.find()) {
    System.out.println(matcher.group(1) + " => " + matcher.group(2));
}

结果:

prop1 => value1
prop2 => <![CDATA[String test='1234';int i=4;]]>
prop3 => value3