我正在尝试使用正则表达式检查文本行。
1,3,4,5,8,10,12,14,19,14
这里的数字用','分隔,并且应该是非negetive并且小于或等于20。 并且任何数字都不应该重复。 这是我的模式。
^(?:(?:0[1-9]|[1-9]|1[0-9]|20),)*(?:0[1-9]|[1-9]|1[0-9]|20)$
但它无法检查重复。我怎么检查呢?
答案 0 :(得分:7)
你想做的事情并不复杂。如果字符串中再次出现此数字,您只需要在每个匹配的数字后检查:
^(?:(0[1-9]|[1-9]|1[0-9]|20),(?!.*\b\1\b))*(?:0[1-9]|[1-9]|1[0-9]|20)$
查看并测试here on Regexr。
在C#中:
string[] myStrings = { "1",
"1,2",
"01,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20",
"01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20",
"01,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,5",
"01,02,03,04,05,06,07,08,13,09,10,11,12,13,14,15,16,17,18,19,20" };
Regex reg = new Regex(
@"^
(?:(0[1-9]|[1-9]|1[0-9]|20),
(?!.*\b\1\b) # Fail if the before matched number occurs once more
)*
(?:0[1-9]|[1-9]|1[0-9]|20)
$",
RegexOptions.IgnorePatternWhitespace
);
foreach (string myString in myStrings)
Console.WriteLine("{0} {1} a valid string.",
myString,
reg.IsMatch(myString) ? "is" : "is not"
);
Console.ReadLine();
答案 1 :(得分:4)
正如你用C#和Java标记了你的问题,我不会在这里给你一个代码解决方案,但基本的想法。
如果您将字符串拆分为,
,则会得到一个子字符串列表:"1", "3" , "4", "5", "8", "10", "12", "14", "19", "14"
。现在,您可以循环遍历这些并尝试将每个解析为整数。如果失败,则不是数字。如果成功,您可以轻松检查它是< 0
还是> 20
。您还可以保留一组之前已有的数字,并检查当前的数字是否重复。
最重要的是,您不应该尝试使用所有内容的正则表达式。而且你的语言要求不是regular(如果你需要记住东西,或计算东西,通常不是常规的)。基于Perl的RegExps能够比常规更多,但这还不够。
正如你在评论中所说,一行最多只能容纳20个数字。由于每个数字也被限制在0到20之间,因此您可以获得线条实际外观的可能性。因此,您拥有有限的语言(具有有限数量的可能行)。有限语言是常规语言的子集,因此,您可以“轻松地”使用正则表达式来表示语言。
最简单的解决方案是只列出每条可能的行。所以,如果你每行只有3个数字,其中5个是最高的数字(为了简单起见),正则表达式可能如下所示:
0,1,2|0,1,3|0,1,4|0,1,5|0,2,3|0,2,4|0,2,5|0,3,4|0,3,5|0,4,5|1,2,3|1,2,4|1,2,5|1,3,4|1,3,5|1,4,5|2,3,4
当然,你可以简化那么多(甚至更多):
0,(1,(2|3|4|5)|2,(3|4|5)|3,(4|5)|4,5)|1,(2,(3|4|5)|3,(4|5)|4,5)|2,(3,(4|5)|4,5)|3,4,5
但是,是的,如果你有一个要求使语言有限,它也会有规律,但不一定很漂亮;我认为“手动”解决方案仍然更具可读性,特别是更灵活。
答案 2 :(得分:2)
正则表达式不是最好的选择。对于重复数字,它太快了。您可能希望查看标记化。即使是寻找不存在的模式这样的简单事情也很困难(例如,请参阅Regular expression to match a line that doesn't contain a word?)
我会用commmas拆分字符串,然后将它们添加到有序列表中。如果使用C#:
"1,2,3,4".Split(',')
开始然后继续Linq以查看您的条件是否满意。
如果您必须使用正则表达式执行此操作,请查看迭代集合搜索返回。但是这对于上面的解决方案来说很少购买。
答案 3 :(得分:1)
String[] numbers = input.split(",");
Set<Integer> filtered = new TreeSet();
for(String number: numbers) {
if(!number.startsWith("-") {
int nbr = Integer.parseInt(number);
if(nbr < 20) {
filtered.add(nbr);
}
}
}
for(int nbr: filtered) {
System.out.print(nbr + " ");
}
答案 4 :(得分:0)
既然你想要正则表达式,是的,你将受到后向引用的限制,因为它们只从\ 1到\ 9。所以你需要排除配对。你最大的挑战是摆脱重复的数字。
来自http://www.regular-expressions.info/refadv.html
将(?:(\d?\d),?)+
与(?!<regex>)
一起使用,以确保您没有重复项。您也可以使用
(?(?=<regex>)true|false)
我使用此页面进行实验:http://www.regextester.com/