集合中的每个元素最多可以使用Regex以任何顺序出现一次

时间:2013-12-07 01:32:07

标签: java regex

我从一个看起来像这样的文件中获得输入:

Key0=Value0;Key1=Value1;Key2=Value2

假设有3个密钥,我需要验证每个密钥最多出现一次,除了Key0只发生一次并且将在开头,但它们可能没有被排序。目前我使用的正则表达式如下:

"^Key0=[\\w](;Key1=[\\w])?(;Key2=[\\w])?(;Key2=[\\w])?;?"

实际上有超过3个键,所以过于冗长可能是不可行的。这个想法是,这应该匹配上面提到的第一个字符串,但也匹配以下字符串:

Key0=Value0;Key1=Value1
Key0=Value0;Key2=Value2
Key0=Value0;Key2=Value2;Key1=Value1

而不是这些字符串中的任何一个:

Key0=Value0;Key1=Value1;Key1=Value1;Key2=Value2
Key0=Value0;Key1=Value1;Key1=Value1;Key2=Value2;Key2=Value2
Key0=Value0;Key2=Value2;Key1=Value1;Key2=Value2

我不确定返回引用组或(?>...)语法是否有用。任何想法都表示赞赏。 (我也在使用Java正则表达式引擎)。

3 个答案:

答案 0 :(得分:1)

这个正则表达式似乎满足了你的需求:

"^Key0=\\w+(?:;(?:(?!\\1)Key1()|(?!\\2)Key2()|(?!\\3)Key3())=\\w+)*$"

...或可读版本:

(?x)
^Key0=\w+
(?:;
  (?:
    (?!\1)Key1() |
    (?!\2)Key2() |
    (?!\3)Key3()
  )=\w+
)*$

在匹配每个键名时,其后面的空组也匹配。虽然它不消耗任何角色,但据说仍然参加了比赛。从那时起,对该组的反向引用将成功(再次消耗任何东西)。因此,每个名称前面的负面预测 会阻止该名称多次匹配。

但是除非你绝对不得不使用它(例如,如果正则表达式是问题的唯一部分,你可以控制)。几乎任何其他方法都比饲养和照顾这种野兽更可取。 :d

答案 1 :(得分:1)

将此负面预测添加到正则表达式的开头:

^(?!.*Key\d+=(.*?);.*Key\d+=\1(;|$))

这使用后向引用来断言没有重复的值。

我还会将主正则表达式简化为:

^(Key\d+=[^;]+(;|$))+

将所有内容放在一起,正确转义为java:

^(?!.*Key\\d+=(.*?);.*Key\\d+=\1(;|$))(Key\\d+=[^;]+(;|$))+$

答案 2 :(得分:0)

不建议在整个列表中使用正则表达式。

相反,您可以像;那样分开:

String string = "Key0=Value0;Key1=Value1;Key2=Value2";
String[] keys = string.split(";");

然后遍历生成的集合,如下所示:(道歉,我不是java程序员,无法提供确切的语法):

for (String pair : keys)
{
    String[] key = pair.split("=");
    ## replace 'pair' with key[0] ##
}

for (String key : keys)
{
    ## check for duplicate key in keys ##
}