我在写正则表达式方面很弱,所以我需要一些帮助。我需要一个正则表达式,可以验证字符串是一组字母表(字母表必须是唯一的),用逗号分隔。
只有一个字符,之后是逗号
示例:
A,E,R
R,A
E,R
由于
答案 0 :(得分:3)
您可以使用重复的群组验证它是否为逗号分隔字符串。
^[AER](?:,[AER])*$
如果没有独特的字符,您可以执行以下操作:
^([AER])(?:,(?!\1)([AER])(?!.*\2))*$
答案 1 :(得分:2)
如果我理解正确,一个有效的字符串将是一个系列(可能是零长)的双字符模式,其中每个模式是一个字母后跟一个逗号;最后一封信终于紧随其后。
因此:
"^([A-Za-z],)*[A-Za-z]$"
编辑:由于您已澄清这些字母必须是A,E或R:
"^([AER],)*[AER]$"
答案 2 :(得分:2)
像这样"^([AER],)*[AER]$"
@Edit:关于唯一性,如果你可以删除"最后一个字符不能是逗号"要求(可以在正则表达式之前以恒定时间检查)然后这应该有效:
"^(?:([AER],?)(?!.*\\1))*$"
这将匹配A,E,R,
因此您需要在执行正则表达式之前进行检查。我不对表演负责,但因为它只有3个字母......
上面显然是一个java正则表达式,如果你想要一个纯粹的"" ^(?:([AER],?)(?!.*\1))*$
@ Edit2:抱歉,错过了一件事:这实际上需要检查,然后你需要在最后添加一个逗号,否则它也会匹配A,E,E
。我知道的那种有限的。
答案 3 :(得分:1)
我们对此正则表达式有几点建议:
^([AER],)*[AER]$
确实有效。但是,要匹配String,它首先必须备份一个字符,因为它会发现最后没有,
。所以我们为此来改变它以提高性能:
^[AER](,[AER])*$
请注意,这会在第一次尝试时匹配正确的String。但请注意,我们不必担心( )*
完全支持;它将首次匹配,或者根本不匹配String。因此,我们可以通过使用占有量词来进一步提高性能:
^[AER](,[AER])*+$
这将获取整个String并尝试匹配它。如果它失败了,它就会停止,通过不进行无用的备份来节省时间。
如果我试图确保字符串没有重复元素,我就不会使用正则表达式;它只会让事情复杂化。你最终会得到不太可读的代码(遗憾的是,大多数人都不了解正则表达式),而且往往代码速度较慢。所以我会建立自己的验证器:
public static boolean isCommaDelimitedSet(String toValidate, HashSet<Character> toMatch) {
for (int index = 0; index < toValidate.length(); index++) {
if (index % 2 == 0) {
if (!toMatch.contains(toValidate.charAt(index))) return false;
} else {
if (toValidate.charAt(index) != ',') return false;
}
}
return true;
}
这假设您希望能够传入一组允许的字符。如果您不想要并且想要匹配明确的字符,请将if (index % 2 == 0)
块的内容更改为:
char c = toValidate.charAt(index);
if (c == 'A' || c == 'E' || c == 'R' || /* and so on */ ) return false;
答案 4 :(得分:1)
我自己的丑陋但可扩展的解决方案,它将禁止使用前导和尾随逗号,并检查字符是否唯一。
它使用前向声明的反向引用:请注意第二个捕获组如何位于对其(?!.*\2)
的引用之后。在第一次重复时,由于第二个捕获组没有捕获任何内容,因此Java会将第二个捕获组引用文本匹配的任何尝试视为失败。
^([AER])(?!.*\1)(?:,(?!.*\2)([AER]))*+$
Demo on regex101(对于这种情况,PCRE风格具有相同的行为)
测试用例:
A,E,R
A,R,E
E,R,A
A
R,E
R
E
A,
A,R,
A,A,R
E,A,E
A,E,E
X,R,E
R,A,E,
,A
AA,R,E