模式匹配 - 正则表达式

时间:2017-07-06 12:35:08

标签: java regex

用户输入格式:

  

[fieldname1]比较器[fieldvalue1,fieldvalue2,value3],[fieldname2]   比较器[fieldvalue1,value2,..],..

需要将其解析为:

  

1. [fieldname1]比较器[fieldvalue1,fieldvalue2,value3]

     

2. [fieldname2]比较器[fieldvalue1,value2,..]等等

(即)每个字段及其比较器和值必须分开。 而比较器将是以下任何一种:

  

< = |> = | = |是|< |> | startswith |开始于| Beginswith |开始于|结束   与|的endsWith |

包含

我使用的正则表达式:

  

([()+。?](\ S)(小于= |> = | = |是|< |> | startswith |开始   与| Beginswith |开始|结束   与|的endsWith |包含)(\ S) [?()+](\)*)

示例: [公司]包含[abc,efg],[email]包含[cdf,test] 正确解析上面没有问题。

问题: 当字段名称或字段值包含符号“[”或“]”时,解析出错。

示例: [company]包含[ab [] c,efg],[email]包含[siva,test]

上面有效,但是因为[]用作分隔符,所以它会停止解析,直到[company]包含[ab []但我希望它能正确解析,例如,

1. [company]包含[ab [] c,efg]

2. [email]包含[siva,test]

感谢。

3 个答案:

答案 0 :(得分:0)

您可以尝试使用此正则表达式:

,(?=(?:(?:[^\\[\\]]*[\\]\\[]){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]
]

Regex101Demo

  

说明:

每当找到a时,>

,(?=(?:(?:[^\\[\\]]*[\\]\\[]){2})*[^\\[\\]]*$)

正向前看会一直运行到字符串末尾,其中包含以下行

(?:[^\\[\\]]*[\\]\\[]){2})*确保 - 如果找到括号,则会发现两次。然后最后一个*表示0或更多重复的括号对。

为什么这很重要?从任何逗号开始,然后计算[和]括号的数量。如果之后只有偶数个括号,您将看到只需要用该逗号分隔。并且你不想分开逗号,之后有奇数括号。这就是解释。

对于正则表达式的完整细分,您可以查看右上方逐个字符给出完整解释的链接。

答案 1 :(得分: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);

答案 2 :(得分:0)

首先,我们必须定义一个与名称匹配的正则表达式,另一个匹配比较器的正则表达式,以及与值匹配的第三个正则表达式:

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

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