前端学习:正则表达式(RegExp)篇

正则表达式(Regular Expression,RegExp)相信对很多人来说,是一个‘熟悉的陌生人’。熟悉是因为我们知道他是很多语言不可缺少的一部分,而且很高效,但又会因为其相对复杂难记的规则而感到陌生!(总是以为记住了,到用时却。。。拼命翻书ing)但是作为一名合格的程序员,尤其前端程序员,需要经常处理一些字符串或者从文本中筛选一些信息,那么对正则的掌握必不可少!(我有什么办法,自己选的路,哭着也要学啊!啊!啊!)

image.png

1. 表达式结构和声明

正则表达式基本结构包括两部分,匹配规则和标识符,其中匹配规则包含在两个‘/’中,标识符在最后,形如/匹配规则/标识符

  • 标识符包括
    1. g:global,全局
    2. i:ignoreCase,大小写不敏感
    3. m:multiline,匹配多行
  • 对象声明方式有两种:
    1. 字面量,即let reg = /[abc]/i
    2. 通过new关键字,如let reg = new RegExp('[abc]','i'),构造函数包括两个参数,参数一字符串表达式(有些字符需要转义,如双引号''等),参数而为标识符
  • 对象属性
    1. globalignoreCasemultiline分别对应标识符g i m使用状况
    2. lastIndex:下一次exec匹配开始的索引
    3. source:正则表达式源码文本
  • 方法
    1. test:测试,返回boolean类型
    2. exec:执行,返回匹配的字符串及分组

2. 表达式因子

所谓的匹配规则,便是有限个表达式因子的规则组合,组合规则当然要根据其功能来决定。主要的表达式因子及其含义如下,式中...代表需要填入的内容:

  • /:前面提到的表达式结构的一部分,由两个/包含规则便创建了一个字面量正则表达式,如/ab/i,匹配带有ab的字符串
  • \:转义符,相信有编程基础的都应该知道,想要吧一些特殊字符当做字符串处理或者表示一些字符串不能表示的字符需要转义,如/\/a/,匹配带有/a的字符串,而/n表示换行符等。RegExp中需要转移的因子大致有\/[](){}?+-*|.^$
  • ^:当在匹配规则前面使用时表示开始符,如/^[ac]/,表示匹配以a或c开始的字符串;但当在一个字符类前面使用时表示取反,如/^[^ac]/表示
// RegExp
// 执行函数
function exec(reg,str){
    let result = reg.exec(str)
    console.log(result)
    return result
}
// 匹配以a开始的字符串
let reg = /^[a]/,
str1 = 'and',
str2 = 'but'
exec(reg,str1) // [ 'a', index: 0, input: 'acnd' ]
exec(reg,str2) // null
// 取反 匹配不以a开始的字符串
reg = /^[^a]/
exec(reg,str1) // null
exec(reg,str2) // [ 'b', index: 0, input: 'but' ]
  • $:结束符,显而易见,就是匹配以某种形式结束的字符串
// 匹配不以结尾的字符串
reg = /[^t]$/
exec(reg,str1) // [ 'd', index: 2, input: 'and' ]
exec(reg,str2) // null
  • -: 表示范围,如[a-z],表示小写字母az;当需要表示-是需要转义,即/\-/,即匹配含有-的字符串
  • +: 表示必选,需要匹配的字符至少出现一次,也可表示为{1,}
  • ?: 表示可选,需要匹配的字符出现0或1次,也可表示为{0,1}
  • *: 表示可有可无,需要匹配的字符出现0或多次,也可表示为{0,}
  • [...]:方括号表示一个字符类,如[abc][123]或者[abc123],类似于编程里面的Class
  • {m,n}:花括号表示对匹配字符出现次数的限定,其中m为最少出现次数,n为最多出现次数;当出现次数最多没有限制的时候,n可空缺
  • (...):圆括号括起来的内容表示一个捕获分组
  • (?:...):圆括号内以?:开始的为非捕获分组,不会返回字符串分组,效率更高
// 下边来比较一下捕获分组与不可捕获分组的区别
let str  = 'Hello World!',
// 捕获分组
reg = /([a-z]+)\s([a-z]+)/i
let resultAry =exec(reg,str) // [ 'Hello World',  'Hello',  'World',  index: 0,  input: 'Hello World!' ]

// 插一句 获取分组结果的方式
// 方式1 数组索引 o为原始字符串,后续为分组
console.log(resultAry[1]) // 分组1:'Hello’
console.log(resultAry[2])  // 分组2:'World’

// 方式2 通过RegExp对象的'$索引'来获取,索引范围'1-9';但是这种方式需要在'reg.exec或test'后立即调用,或者字符串的`match、search、split`等方法
console.log(RegExp.$1) // 分组1:'input’
console.log(RegExp.$2)  // 分组2:'’
// 像这样才有效
reg.exec(str) 
console.log(RegExp.$1) // 分组1:'Hello’
console.log(RegExp.$2)  // 分组2:'World’

// 非捕获分组
reg = /(?:[a-z]+)\s(?:[a-z]+)/i
exec(reg,str) // [ 'Hello World', index: 0, input: 'Hello World!' ]
// 通过比较我们发现,非捕获分组确实不会返回字符串分组,即['Hello','World']
  • .: 匹配除换行符 \n 之外的任何单字符
  • \d: 匹配数字,相当于[0-9]
  • \s: 匹配空白(whitespace)

3. 举例分析:邮箱地址匹配

假设邮箱验证规则为:只允许英文字母、数字、下划线、英文句号、以及中划线组成,且下划线和中划线不得出现在开始和结束位置,区分大小写。

let reg = /^([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9]+)@([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9]+).([a-zA-Z]+)$/;

let email1 = '@hsajdh.com',
    email2 = '_dnaksl_@.com',
    email3 = '-absdbn_dnaksl_@hsajdh.',
    email4 = 'absdbn_dnaksl@hsajdh.com_',
    email5 = 'absdbn_dnaksl@hsajdh.com'

console.log(reg.test(email1)) // false
console.log(reg.test(email2)) // false
console.log(reg.test(email3)) // false
console.log(reg.test(email4)) // false
console.log(reg.test(email5)) // true
  • 解释说明
    1. 首先邮箱地址分为三组,名称@域名.后缀(假设只有一级域名),得到/^()@().()$/
    2. 名称由字母、数字、下划线和中划线组成,且下划线和中划线必须出现在中间(可选,记得中划线要转义),得到([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9])+
    3. 域名和名称规则一样,也为([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9])+
    4. 后缀只能回字母,得到[[a-zA-Z]+]
    5. 最终的表达式为/^([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9]+)@([a-zA-Z0-9]+[_\-]?[a-zA-Z0-9]+).([a-zA-Z]+)$/

参考


如果您感觉有所帮助,或者有问题需要交流,欢迎留言评论,非常感谢!
前端菜鸟,还请多多关照!


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容