public static void Lesson2(){
Console.WriteLine("是否为合法的电话号码,电话号码的规则分两部分:");
Console.WriteLine("固话为7-8位,手机为11位,且由1开头,且都为数字。");
string landPhoneRule = @"^\d{7,8}$";
string handPhoneRule = @"^1\d{10}$";
//规则合并
string rule = string.Format("{0}|{1}", landPhoneRule, handPhoneRule);
string[] enters ={
"1234567", //7位数字,合法
"12345678", //8位数字,合法
"13888888888", //11位以1开头的数字,合法
"23888888888", //11位以2开头的数字,非法
"0123456789", //10位数字,非法
"1388888888a",//带有字符,非法
"10111111111"//11数字,合法
};
foreach (var enter in enters){
Console.WriteLine(Regex.Match(enter, rule));
}
Console.WriteLine("现改变手机的规则,改为:手机要以数字1开头,且第二位和第三位不能有数字0,其他不变");
handPhoneRule = @"^1[1-9]{2}\d{8}$";
rule = string.Format("{0}|{1}", landPhoneRule, handPhoneRule);
foreach (var enter in enters){
Console.WriteLine(Regex.Match(enter, rule));
}
}
我们看到10111111111也能匹配,显然这不是个手机号,因此在后面我更改了规则,添加了第二位和第三位不是0的限制。这时 \d 不满足条件了,查看手册,发现 [] 字符,可以在里面添加候选字符,例如 [123] 指匹配123,也可以用 - 来添加范围,如 [0-9] 和 \d 是一样的。那么更改后的手机号码匹配的规则就变成了 ^1[1-9]{2}\d{8}$ 。下面是第三课。
Lesson3 判断IP是否合法
这一题,我将IP的判断稍微简化了些,规则是必须是 ***.***.***.*** ,其中每项的字符数最少为1位,最多为3位,且 255>=*** >= 0, 第一项不能为0\00\000。这一题的判断要复杂的多,您也能看到正则表达式的一个”短板“,那就是不能获取字符的意义,后面我会解释这一点。看条件,基本的语法我前面都介绍了,该规则可以拆分为两部分,第一项和后三项。第一项,255>=*** >= 0, 且不能为0\00\000。我在思考这道题的时候,先按照正向的思路想,即”描述什么样的满足条件“,情况非常多,01,001,011,1-249,250-255,一共这么多种情况,正则表达式是没有办法”忽略“的,如果是数字, if (001 == 1)是成立的,但是正则表达式办不到,你只能 (0[2]1)|1 来描述1和001都满足条件,这就是我前面说的,无法获取字符本身的意义,你只能每一位的描述一个字符串,第一位是什么,第二位不是什么,而无法通过意义来形容字符串。我通过”正向”的列举每种情况,表达式是这样的:(0{2}[1-9]|0[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|0[1-9]|[1-9]\d|[1-9]) 。其意义大概就是把01,001,011,1-249,250-255的全部情况都列举了出来,这么做没什么“错”,但是太长了,有没有什么简便做法?“正向”思考不行,那么我们来“反向”试一下:第一项是1-3个数字,不能全是0,不能大于255,也就是不能是 ^0{1,3},2[6-9]\d,25[6-9],[3-9]\d{2},只要不是前面的条件,就可以。如何形容不满足的条件? [^]可以,但是只能指明一个字符。可以看到手册的下面有几个?<!这样的字符,他们表示“附近是否满足条件”,举个例子:?! 加一起表示正向否定的预查找, Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”,还有其他的。这里我用?<! ,表示反向否定查找,即(?<!123)456表示能匹配23456,但是不能匹配前面带123的456,如123456就不满足条件。这个正向和反向就是前面和后面,肯定就是匹配,否定就是排除。我的第一项的表达式是:^(\d{1,3})(?<!^0{1,3}|2[6-9]\d|25[6-9]|[3-9]\d{2}),第二项的前面如果是上述几种情况,则第二项永远不会匹配。接下来是后面三项,后面的三项都是 .***,255>=***>=0,语句是(.[01]?\d?\d|2[0-4]\d|25[0-5]){3}$,加起来就是 ^(\d{1,3})(?<!^(0{1,3}|2[6-9]\d|25[6-9]|[3-9]\d{2}))(.[01]?\d?\d|2[0-4]\d|25[0-5]){3}$ 。代码如下: