转载

正则表达式实践篇

  1. 与搜索字符串开始处的 3 个数字匹配: /^/d{3}/
  2. 与除 a、b 和 c 以外的任何字符匹配: /[^abc]/
  3. ‘1234567’.match(//d{1,3}/g),根据贪婪原则,结果是 ["123", "456", "7"]
  4. 不以“th”开头的单词匹配: //b(?!th)/w+/b/
  5. 对密码应用以下限制:其长度必须介于 4 到 8 个字符之间,并且必须至少包含一个数字: /^(?=.*/d).{4,8}$/ 。首先.{4,8} 表示与包含 4-8 个字符的字符串匹配;然后.*表示单个字符(除换行符 /n 外)零次或多次,且后面跟着一个数字,注意(?=)只匹配一个位置。
  6. 匹配一个中文字符: /[/u4e00-/u9fa5]/

当然,可能答案不唯一,不必较真啦~ 主要目的是回忆熟悉一下语法~

如果还不了解正则,可以前往正则表达式理论篇 了解哇~

真正的实践来了

要想在复杂性和完整性之间取得平衡,一个重要因素是要 了解将要搜索的文本

好的正则表达式:

  • 只匹配期望的文本,排除不期望的文本
  • 易于控制和理解
  • 保证效率

有时候处理各种极端情况会降低成本/收益的比例。所以某些情况下,不完全依赖正则表达式完成全部工作,比如某些字段用子表达式()括起来,让内存记忆下来,然后再用其他程序来验证。

不过本文还是从学习正则的角度出发,全部依赖正则表达式来写的哇~~

匹配美元

正则表达式: /^/$[0-9]+(/.[0-9][0-9])?$/

分为四部分:

  • ^/$ 以美元符号开头。
  • [0-9]+ 至少包含一个数字。
  • (/.[0-9][0-9])? 由一个点和两位数组成,匹配0次或1次,因为可能是整数或者是小数。
  • $ 最后的$表示以数字结尾的。

缺点:不能匹配$1,000

匹配24小时制的时间,比如 09:59

  • 小时部分

方法一:分类逻辑为第一个数字(0、1、2),可以分为三部分:上午 00点到09点( 0可选 );白天10到19点;晚上20到23点。

因此有三个多选分支,得到的结果为:

0?[0-9]|1[0-9]|2[0-3]

还可以优化一下,合并前面的两个多选分支,得到:

[01]?[0-9]|2[0-3]

方法二:分类逻辑为第二个数字,可以分为两部分:[0-3]和[4-9]。为什么这么分?看看下面这个图就知道了,[0-3]多了一行(以2为第一个数字):

正则表达式实践篇

因此有两个多选分支,结果为:

[012]?[0-3]|[01]?[4-9]
  • 分钟部分

分钟数比较简单,第一个数范围在0-5之间,第二个数在0-9之间,因此得到分钟数为:

[0-5][0-9]
  • 最后的结果:

小时部分用(?:)包起来,起到一个分组的作用,且不保存匹配项;

冒号、分钟数拼起来;

最后加上一个分界 /b 表示单词的开始或结束,得到最终的结果:

//b(?:[01]?[0-9]|2[0-3]):[0-5][0-9]/b/
// 或者
//b(?:[012]?[0-3]|[01]?[4-9]):[0-5][0-9]/b/
  • 验证:
var reg = //b(?:[01]?[0-9]|2[0-3]):[0-5][0-9]/b/;
'现在是09:49点'.match(reg);	// ["09:49"]
'现在是009:490点'.match(reg);	 // null

其实这个结果不能说完全正确,首先你要明白这个正则用在什么地方,比如是数据验证或者

复杂的字符串搜寻替换。

情景一:填写表单中的字符串必须为24小时制的时间,那么可能第一个 /b 需要改成^,第二个 /b 改成 $

情景二:用于复杂的字符串搜寻替换时,可能也会匹配这样子的字符串如’跑步用时19:50’,明显的,’19:50’表示19分50秒,而不是表示24小时制的时间19点50分。

匹配IP地址

IP地址的规则:点号分开的四个字段,每个字段在0-255之间。

  • 第一步:

如果一个字段是一个数或两个数,肯定是在0-255的范围内的;

如果三位数,那么以0或者1开头的三位数也是合法的,即000-199。

从上面的陈述中我们就可以得到三个多选分支:

/d|/d/d|[01]/d/d

我们稍微合并一下这三个多选分支,得到:

[01]?/d/d?
  • 第二步:

我们再来看以2开头的三位数:

第二位数小于5的时候,第三位数范围[0-9]都可以;第二位数等于5的时候,第三位数范围[0-5] ,因此得到两个多选分支:

2[0-4]/d|25[0-5]
  • 第三步:

前两步合并起来,得到一个字段0-255的表示方法:

[01]?/d/d?|2[0-4]/d|25[0-5]
  • 第四步:

四个字段合并起来,IP地址正则如下:

/^(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])$/

点号要转义一下,^和$需要加上,否则可能匹配52123.3.22.993,因为其中的123.3.22.99是符合的。(?:)起到分组的作用,且不保存匹配项。

一些测试结果:

var reg = /^(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])$/;

'123.11.22.33.44'.match(reg); // null
'52123.3.22.993'.match(reg);  // null
'123.11.22.33'.match(reg);  // ["123.11.22.33"]
'0.0.0.0'.match(reg); 	// ["0.0.0.0"]

虽然0.0.0.0是合法的,但它是非法的IP地址,使用正则的否定顺序环视功能(零宽负向先行断言),可加上(?!0+.0+.0+.0+$) :

var reg = /^(?!0+.0+.0+.0+$)(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])/.(?:[01]?/d/d?|2[0-4]/d|25[0-5])$/;

'123.11.22.33'.match(reg); // ["123.11.22.33"]
'0.0.0.0'.match(reg);  // null
原文  https://aotu.io/notes/2016/12/07/regexp-practice/
正文到此结束
Loading...