我从一个看起来像这样的文件中获得输入:
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正则表达式引擎)。
答案 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 ##
}