模式匹配 - 正则表达式



用户输入格式:

[字段名称 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
= "[^,\[\]]*(?:\[[^,\[\]]*\][^,\[\]]*)*";

在这里,值不能包含任何逗号,只能包含平衡括号,而不嵌套。

最新更新