用户输入格式:
[字段名称 1] 比较器 [字段值 1,字段值 2,值 3],[字段名称 2] 比较器 [字段值 1,值 2,..],..
需要将其解析为:
1.[字段名称 1] 比较器 [字段值 1,字段值 2,值 3]
2.[字段名称2]比较器[字段值1,值2,..]等
(即)每个字段及其比较器和值必须分开。 而比较器将是以下任何一种:
<=|>=|=|is|<|>|startswith|开始于|开始于|开头为|结束 与|尾声|
包含
我使用的正则表达式:
([(.)+?](\s)(<=|>=|=|is|<|>|startswith|开始 与|开始于|开头为|结束 与|Endswith|contains)(\s)[(.)+?](\,)*)
示例:[公司] 包含 [abc,efg],[电子邮件] 包含 [cdf,test] 以上正确解析没有问题。
问题:当字段名称或字段值包含符号"["或"]"时,解析出错。
示例:[公司] 包含 [ab[]c,efg],[电子邮件] 包含 [SIVA,测试]
以上是有效的,但由于 [] 用作分隔符,它停止解析直到 [公司] 包含 [ab[],但我希望它像上面一样正确解析,例如,
1.[公司] 包含 [ab[]c,efg]
2.[电子邮件] 包含 [SIVA,测试]
谢谢。
你可以试试这个正则表达式:
,(?=(?:(?:[^\[\]]*[\]\[]){2})*[^\[\]]*$)
拆分目标字符串应提供拆分结果集的列表。您可以在其上轻松应用比较器匹配
final String regex = ",(?=(?:(?:[^\[\]]*[\]\[]){2})*[^\[\]]*$)";
final String string = "[company] contains [ab[]c,efg],[email] contains [siva,test]";
String[] res=string.split(regex);
System.out.println(Arrays.asList(res).toString());
通过使用它,您可以获得扩展结果。您可能需要检查的是,每个索引是否包含您所示的正确比较器。如果没有,则将其从阵列中删除。
上面的代码输出:
[
[company] contains [ab[]c,efg],
[email] contains [siva,test]
]
正则表达式101演示
解释:
每当找到 时,就会找到 -->
,(?=(?:(?:[^\[\]]*[\]\[]){2})*[^\[\]]*$)
积极的展望一直持续到字符串的末尾,其中下一行
(?:[^\[\]]*[\]\[]){2})*
确保 - 如果找到括号,则找到两次。然后最后一个 * 表示括号对的重复次数为 0 或多次。
为什么这很重要?从任何逗号开始,然后计算[和]括号的数量。您将看到,如果之后只有偶数个括号,则只需要按逗号进行拆分。而且您不想为后面出现奇数括号的逗号进行拆分。这就是解释。
对于正则表达式的完整细分,您可以查看链接,其中在右上角逐个字符给出了完整的解释。
所以基本上你需要在]
和[
之间的每个,
拆分字符串。
如果您使用谷歌的番石榴,您可以使用Splitter
并在正则表达式上拆分,具有正前]
和正面后视[
String s = "[fieldname1] comparator [fieldvalue1,fieldvalue2,value3],[fieldname2] comparator [fieldvalue1,value2]";
Pattern stringPattern = Pattern.compile("(?<=\]),(?=\[)");
Iterable<String> split = Splitter.on(stringPattern).omitEmptyStrings().split(s);
split.forEach(System.out::println);
首先,我们必须定义一个与名称匹配的正则表达式,另一个与比较器匹配的正则表达式,以及第三个与值匹配的正则表达式:
private static final String NAME_RE = "[A-Za-z0-9_]+";
private static final String VALUE_RE = "[A-Za-z0-9_\[\]\.]+";
private static final String COMPARATOR_RE
= "<=|>=|=|is|<|>|startswith|Starts with|Beginswith|Begins with|Ends with|Endswith|Contains";
现在,我们可以创建组合这些子正则表达式的模式:
private static final String RE = "\s*\[(" + NAME_RE + ")\]\s*"
+ "(" + COMPARATOR_RE + ")\s*\[\s*("
+ VALUE_RE + "(?:\s*,\s*" + VALUE_RE + ")*)\s*\]"
+ "(?:\s*,\s*(.*))?";
private static final Pattern PATTERN
= Pattern.compile(RE, Pattern.CASE_INSENSITIVE);
请注意,它匹配单个规则,该规则后面可能跟逗号,也可能不跟逗号和其他规则。
源字符串的分析必须迭代规则:
private static void parse(String source) {
String s = source;
while (s != null) {
Matcher matcher = PATTERN.matcher(s);
if (!matcher.matches()) {
throw new IllegalArgumentException("Invalid syntax: " + source);
}
String name = matcher.group(1);
String comparator = matcher.group(2);
String values = matcher.group(3);
s = matcher.group(4);
System.out.println("[" + name + "] " + comparator + " [" + values + "]");
}
}
现在让我们尝试解析您的两个示例:
private static final String EXAMPLE1 = "[company] contains [abc,efg],[email] contains [cdf,test]";
private static final String EXAMPLE2 = "[company] contains [ab[]c,efg],[email] contains [siva,test]";
public static void main(String[] args) {
parse(EXAMPLE1);
parse(EXAMPLE2);
}
它产生以下输出:
[company] contains [abc,efg]
[email] contains [cdf,test]
[company] contains [ab[]c,efg]
[email] contains [siva,test]
更新:
请注意,必须限制值的内容,因为如果"efg]"和"[email] 包含 [cdf"都是可接受的值,则无法知道这些示例是由一个还是两个规则组成的。
更新 2:
这是一个非常松散的正则表达式VALUE_RE:
private static final String VALUE_RE
= "[^,\[\]]*(?:\[[^,\[\]]*\][^,\[\]]*)*";
在这里,值不能包含任何逗号,只能包含平衡括号,而不嵌套。