从零开始学正则(一)

 壹 ? 我为什么学正则

正则表达式是从侧面衡量一个程序员水平的标准,可以很肯定的说没有哪位高级开发不懂正则。在前端开发中使用正则表达式最频繁的场景莫过于表单验证,判断邮箱,判断手机号格式等等,那么我是怎么解决这些问题的呢,打开百度,输入“正则验证手机”回车,复制粘贴即可。我想大家应该看过不少关于常用正则整理的文章,我不理解正则,反正从来也记下来了。

古人云,熟读唐诗三百首,不会做诗也会吟。我会花三周左右系统化学习正则表达式,若你有兴趣可以与我一同学习(一起受苦),我相信学成之后即使无法立刻写出逼格满满的正则,但对于阅读大部分常见正则应该是没问题的。

另外,正则学习系列文章均为我阅读 老姚《JavaScript正则迷你书》的读书笔记,毕竟此时的我也只是一个学习者。这本书写的真的超级棒,推荐大家下载在闲暇时间阅读。

文中所有正则图解均使用regulex制作。

最后偷偷说一句,公司前端组没一个人懂正则,等我学会了我将是组里第一个略懂正则的人!!

 贰 ? 正则两种模糊匹配

正则表达式是一种匹配模式,要么匹配字符(符合规则的字符),要么匹配位置(符合规则字符所在的位置)。

正则之所以强大,是因为正则能实现模糊匹配;在实际开发中,我们往往需要匹配某一范围的数据。举个贴切的例子,当验证用户输入邮箱格式是否正确,除了“ @ ”等固定字符以外,用户输入的具体字符我们是无法估量和统计的,精准匹配显得无能为力,也只有模糊匹配能巧妙解决这个问题。

正则表达式的模糊匹配分为横向模糊与纵向模糊两种:

1.横向模糊

其实不难理解,横向模糊表示正则匹配的字符长度是不确定的,我们可以通过正则的量词实现横向匹配。不知道大家有没有在B站看到过“233”的弹幕,“233”是一个网络用语,表示大笑的意思。但因为个人输入随心的习惯,可能打出2333,233333等不定长度的弹幕,那么我们匹配弹幕中有多少233大笑可以用正则这么写:

var regex = /23{2,}/; 

这里量词 {2,} 表示前面的3会出现2次或者更多次,量词后面会专门介绍。我们来试试这个正则:

var regex = /23{2,}/g;
var str = ‘223 233 2323 2333‘;
var result = str.match(regex);
result//["233", "2333"]

注意正则后面有个小写的字母g,这是正则修饰符之一,g为global的简写,表示全局匹配。若不加g,match方法只会匹配第一个符合条件的字符。关于修饰符后文会详细介绍。

2.纵向模糊匹配

纵向模糊匹配是指具体某一位置可能有多种字符的情况,横向模糊可以用量词实现,而纵向模糊匹配可以使用字符组实现,比如:

var regex = /[abc]/;

这段正则表示可匹配字母a b c其中一个,我们来看一个简单的例子:

var regex = /a[1-3]c/g;
var str = "a0c a1c a2c a3c a4c";
var result = str.match(regex);
result //["a1c", "a2c", "a3c"]

在这个例子中我们使用了字符组[1-3],它本质上与[123]效果相同,但因为是连贯数字所以支持范围简写。下面介绍具体介绍正则字符组。

 叁 ? 正则字符组

在上一个例子中我们已经了解到字符组[123]可用范围表示法写成[1-3],这是非常有用的,设想一想,我们现在想匹配数字1-9,字母a-f,要写全的话就得这样[123456789abcdef],但通过范围表示法只用短短的[1-9a-f],是不是很奈斯:

现在知道了连字符 - 的作用,那么现在我们就是要匹配1 - 3其中任意字符怎么做呢?有三种写法可解决这个问题,写成[-13]、[13-]或者使用转义符 \ 表示[1\-3]即可。

1.排除字符组

纵向模糊匹配还存在一种情况,就是某个位置可以是除了某几个字符之外的任意字符,比如我希望是除了1-3之外的任意字符,那么我们可以使用[^1-3]表示,注意这里使用了脱字符 ^。

2.常用简写

了解了字符组范围表示法,那么想匹配数字0到9可以写成[0-9],其实它还有一种更简单的写法\d,估计这部分是很多人常忘记的知识,我们来做个整理:

字符组 含义
\d [0-9]表示是一位数字,digit数字。
\D [^0-9]表示除数字以外的任意字符。
\w [0-9a-zA-Z_]表示数字,大小写字母和下划线,word简写,又称单词字符。
\W [^0-9a-zA-Z_],非单词字符。
\s [ \t\v\n\r\f]表示空白符。包含空格,水平制表符,垂直制表符,换行符,回车符,换页符。
\S [^ \t\v\n\r\f],非空白符。
. [^\n\r\u2028\u2029],通配符,表示除了换行符,回车符,行分隔符和段分隔符之外任意字符。

不懂就问,上述表格中空白字符都代表什么意思?这里我测试了下,可能因为语言的问题,很多字符在js环境中没法运行,C语言可以运行可惜我不懂...这里我做了查阅做了整理:

空格:顾名思义,就是我们理解的空格

水平制表符\t:类似于tab键缩进的效果,一般系统中水平制表符占8列,所以根据你按的次数占据8*N列。

垂直制表符\v:让文本从下一行开始输出,且开始的列数为\v前字符的后一列。

换行符\n:从下一行开头开始输出,这个js可以跑。

回车符\r:这里的回车不是我们理解的enter回车另起一行开始输出,而是回到当前行开头输出,还可能将已输入文本替换,替换这一点根据环境不同表现不同。

换页符\f:在输出\f后面文本之前,会先将当前屏幕清空,类似于先清除再输出。

行分隔符和段分隔符,找了一圈也没看到好的解释,这里还望有缘人指点。

那么如果我们想匹配任意字符,有这几种写法[/d/D]、[/w/W]、[/s/S]、[^],其实不难理解,以[/d/D]为例,就是匹配数字以及除了数字以外的所有字符,这不就是所有字符了吗。

 肆 ? 正则量词

在讲述正则横向模糊匹配时已有使用量词的例子,量词表示某个字符的重复次数,我们也将常用量词做个整理:

量词 含义
{m,n} 至少出现m次,最多出现n次。
{m,} 至少出现m次,没有上限。
{m} 等价于{m,m},固定出现m次
? 等价于{0,1},要么不出现,要么出现一次。
+ 等价于{1,},至少出现1次,没有上限。
* 等价于{0,},表示出现任意次数,可以不出现,也可以任意次,包容型比?和+大。


1.贪婪匹配和惰性匹配

正则默认就是贪婪匹配,贪婪就是在量词匹配规则范围内最大限度的去匹配字符,我们来看个简单的例子:

var str = "ab abb abbb abbbb abbbbb";
var regex = /ab{2,4}/g;
var result = str.match(regex);
result //["abb", "abbb", "abbbb", "abbbb"]

在这个例子中,我们匹配2-4个字母b,你给2个我要,给3个我要,哪怕给5个我也要尽我所能拿4个,是不是很贪心。

惰性与贪婪相反,惰性匹配就是在量词匹配范围内以最小限度去匹配字符,无欲无求做人本分,我们只需要在量词后接个?即是惰性匹配,看个例子:

var str = "ab abb abbb abbbb abbbbb";
var regex = /ab{2,4}?/g;
var result = str.match(regex);
result //["abb", "abb", "abb", "abb"]

大家会不会觉得惰性匹配情况下这个次数4是不是没意义了呢?其实并不是没意义,尽管惰性匹配是以最小2次为匹配规则,但被匹配的字符前提条件是满足2-4之间,4还是起到了限制条件,我们改改例子再看:

var str = "abc abbc abbbc abbbbc abbbbbc";
var regex = /ab{2,4}?c/g;
var result = str.match(regex);
result //["abbc", "abbbc", "abbbbc"]

上述例子中当匹配到字段 abbbbbc 时因为字母b已经超过范围,所以不在匹配范围内。惰性可以理解为,在匹配范围内拿最少的东西,我可以过的无欲无求,但也得过的温饱活得下去才行啊。

 伍 ? 正则多选分支

如果说横向模糊匹配和纵向模糊匹配都是一种匹配模式,那如果需要同时使用多种模式怎么办呢,这里我们就可以使用管道符 | 实现这一点,来看个简单的例子:

var str = "a0c a1c a2c a3c abc abbc abbbc abbbbc";
var regex = /a[1-3]c|ab{1,3}c/g;
var result = str.match(regex);
result //["a1c", "a2c", "a3c", "abc", "abbc", "abbbc"]

在这个例子中,我们使用了纵向模糊匹配和横向模糊匹配两种模式。

需要注意的是,分支匹配也是惰性匹配,即前面的匹配模式能满足,后面就不匹配了,来看个例子:

var str = "userName";
var regex = /user|userName/g;
var result = str.match(regex);
result //["user"]

这非常类似于js短路运算符中的||,以a||b为例,倘若a为真那么b就不判断了。

function fn1() {
  console.log(1);
  return true;
};

function fn2() {
  console.log(2);
  return true;
};
fn1() || fn2(); //1

我们再来个反转,情理上来说分支匹配是惰性,但有一种特殊情况,直接上例子:

var str = "userName";
var regex = /Name|userName/g;
var result = str.match(regex);
result //["userName"]

哎?怎么不是匹配Name字段,其实我也有这个疑问,去查了下也没看到合理的解释...我的猜测是,正则是从左往右的匹配机制,若左侧一开始无法匹配成功(user和Name对应不上),则优先考虑了分支其它情况。

var str = "userName";
var regex = /Name/g;
var result = str.match(regex);
result //["Name"]

 陆 ? 总

那么到这里,JavaScript正则迷你书第一章节就看完了。我们做个总结,大家可以看着思维导图回顾下知识点:

另外留两个思考题,尝试写出匹配24小时制的正则匹配,以及匹配16进制颜色值的正则,注意,16进制颜色是支持#dddddd与#ddd两种。

那么到这里本文结束,我也要抓紧时间看第二章节了。

原文地址:https://www.cnblogs.com/echolun/p/12021871.html

时间: 2024-10-11 06:23:57

从零开始学正则(一)的相关文章

从零开始学正则(二)

 壹 ? 引 我在从零开始学正则(一)这篇文章中介绍了正则横向模糊与纵向模糊匹配模式,以及常用的字符组与量词,掌握了这些其实已经算正则入门了.在文尾留下了两个正则问题,请写出匹配24小时制时间与16进制颜色的正则,在学习第二章之前我们先搞定这两个问题. 24小时制时间格式一般是09:30这样,小时的第一位数字可能是[0-2]三种情况之一,当为0,1时,第二位数字可以是[0-9]任意数字,当为2时第二位数字只能是0-3之间的数字.第三位数字只能是0-5之间的数字,最后一位数字只能是0-9之间. 我

从零开始学正则(四)

壹 ? 引 我在从零开始学正则(三)这篇博客中介绍了分组引用与反向引用的概念,灵活利用分组能让我们的正则表达式更为简洁.在文章结尾我们留下了两个问题,一问使用正则模拟实现 trim方法:二问将my name is echo每个单词首字母转为大写. 我们先来分析第一个问题,trim属于String方法,能去除字符串头尾空格,所以我们只需要写一个正则匹配头尾空格将其替换成空即可.空格属于空白符,所以这里需要使用字符组  \s ,空格可能有多个,所以要使用量词 + :其次我们需要匹配紧接开头后与结尾前

从零开始学正则(七:终章)

 壹 ? 引 花了差不多半个月的晚上时间,正则入门学习也步入尾声了,当然正则的学习还将继续.不得不说学习成效非常明显,已能看懂大部分正则以及写出不太复杂的正则,比如帮组长写正则验证文件路径正确性,再如进产品页根据页面地址获取产品id: let pathname = '/webtoprint/dynamicsize-gamebox-2033986.html'; let productId = pathname.match(/\-(\d+)\./)[1]; //2033986 虽然正则都不难,但是相

【高德地图API】从零开始学高德JS API(一)地图展现——仙剑地图,麻点图,街景,室内图

下面是基于KWIC 的关键字匹配算法(管道+过滤器模式下实现) 关键部分的管道+过滤器 软件体系下的实现, 在很多的关键字搜索平台都使用了这一 循环移位+排序输出的 关键字匹配算法: 具体需求如下: 1.使用管道-过滤器风格: 每个过滤器处理数据,然后将结果送至下一个过滤器,.要有数据传入,过滤器即开始工作.过滤器之间的数据共享被严格限制在管道传输 四个过滤器: 输入(Input filter): 从数据源读取输入文件,解析格式,将行写入输出管道 移位(CircularShifter filte

从零开始学android<android事件的处理方式.二十四.>

在android中一共有 多种事件,每种事件都有自己相对应的处理机制 如以下几种 1 单击事件 View.OnClickListener public abstract void onClick (View v) 单击组件时触发 2 单击事件 View.OnLongClickListener public abstract boolean onLongClick (View v) 长按组件时触发 3 键盘事件 View.OnKeyListener public abstract boolean

IC卡解密从零开始学1 (也许会有2) 解密工具V2 V3大放送 By:lookyour

前段时间发了一个破解的PN532工具,详见 ===========================IC卡解密工具 PN532工具XP 爆破版http://www.52pojie.cn/thread-597896-1-1.html IC卡解密从零开始学2  解密工具PN532-mfoc-mfcuk-GUIhttp://www.52pojie.cn/thread-604402-1-1.html =========================有很多人私信和回复希望有个详细点的介绍... 好吧,本着

从零开始学android<RatingBar评分组件.二十三.>

如果现在用户要对某个应用程序打分往往会使用图所示的组件,通过选择的"五角星"的个数来决定最终的打分成绩 这样的功能在Android之中,可以使用RatingBar组件实现,使用此组件可以方便用户的输入,而且很直观,RatingBar类的定义结构如下: java.lang.Object ? android.view.View ? android.widget.ProgressBar ? android.widget.AbsSeekBar ? android.widget.RatingBa

从零开始学android<AutoCompleteTextView随笔提示文本框.十九.>

随笔提示功能可以很好的帮助用户进行方便的信息输入,而在Android之中也提供了与之类似的功能,而这个功能的实现就需要依靠android.widget.AutoCompleteTextView类完成,此类的继承结构如下: java.lang.Object ? android.view.View ? android.widget.TextView ? android.widget.EditText ? android.widget.AutoCompleteTextView No. 方法 类型 描述

从零开始学android<使用嵌套布局实现计算器界面.十七.>

所谓的嵌套布局就是在一个文件中嵌套多个布局文件 <span style="font-size:18px;"> <LinearLayout android:layout_width="match_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:layou