带你入门(几个小小点)
目录
- 正则表达式的使用
- 正则表达式的基本构成元素
- 正则中的类(分类),基本的元字符 + 五个基本类,构成正则的各种变化
- 正则表达式的分组 和 匹配出来的变量引用
- 正则的匹配原理 和 应用
正则表达式中不能正常显示(不能正常使用)的字符基本都可以使用转义来解决
$1 表示分组的第一个字符
\$1 表示一个 `$1` 字符
正则表达式可以快速处理基本字符,文本,网址,邮箱,日期等数据
-
日期的使用
^(\d{4})[/-](\d{2})[/-](\d{2})$ // 请试翻译该正则表达式 2006/02/03 test/07/sd 1998-03-07 12345/23/1998
-
http 协议的使用
http:\/\/(.+\.jpg) // 请试翻译该正则表达式
-
一些常用的正则含义
\d -> digit \b -> word boundary \w -> word $ -> End of line ^ -> Start of line [0-9] -> One of: '0' - '9' [/-] -> One of: '/' '-' (\w) -> group #1 word g -> global i -> ignore case
1.小葵花妈妈课堂正式开课啦. 哈哈,上面的你要是不熟悉就当我是在装逼格高啦!
-
两种实例化RegExp对象的方法 (先来看看 regExp 哥哥长什么1样子)
小时候是这样(长得中规中矩)
var reg = new RegExp("正则表达式",修饰符); // 修饰符是啥?后面聊
长大了长这样(这 TM 长的就很随意啦)
var reg = /正则表达式/修饰符
像上面这样写就可以生成一个 正则对象啦
-
聊聊修饰符 (长相很随意,发型来帮忙)
g (global): 全文搜索,不添加g,搜索到第一个匹配停止; i (ignore case) : 忽略大小写,不添加则默认为大小写敏感; m ( multiple lines):多行搜索 g i m 可以一起使用
-
元字符(就像信息有一元分词,二元分词等)。就是作为正则表达式的
基本构成体
注意:这里的元字符是一个整体并不是简单的一个字符 a,b,c .... 表示一个个元字符 \t, \v, \n ... 也表示一个个元字符 $1, $2 ... 也表示一个个元字符
作为基本字符的元字符(不解释。。。)
-
特殊字符作为元字符
基本构成体
,既然是体,肯定有线条,有孤独,有凹有凸。。。。下面你看到的这些都是元字符 $ ^ | . + ? [] {} () \t 水平制表符 \n 换行符 ......
特殊字符我们暂且
叫 她 元字体
2. 正则也是有族谱的,看看正则相关的分类
-
元字符
元字符每个就代表一个意思,表示取到这个字符的意思(元字体每个也都是单独的意思)
-
字符类 (何为字符类,就是将 字符拼在一块组成一类嘛。物以类聚,人以群分)
-
构成类, 使用 [] 将某些字符构成一类
表示或的意思
[abc] a 或者 b 或者 c [0123456789] 0 或者 1 或者 2 ...等我吐完这口老血一定说到 9
明白了没?构成类表示或者意思
-
字符类取反, ^ 表示取反的意思
[^abc] //不是 a,也不是 b, 也不是 c.. [^0123456789] // 小明你来念
取反表示取这些之外字符。
-
-
范围类 0-9, a,-z, 12-15 就表示一个范围呀
表示这个范围内或的意思
范围类需要结合字符类一起使用,表示这个范围里的或者
范围类是个闭区间
直接上栗子 [0123456789] // 原来你这样写的 [0-9] // 范围类这样写的
[abcdefghigklmnopqrstuvwxyz] // 原来这样写的 [a-zA-Z] //范围类这样写 还比原来写的多
-
JavaScript预定义类
预定义类就是 正则 觉得你写东西不容易,他帮你 预定义一些好用的 类(有一种冷是你妈妈觉得你冷)
解释一下: 1. d -> digit s -> space w -> word 2. 使用之前的 字符类 + 范围类 等也可以实现 预定义类 的匹配,but 预定义类不是更简单吗 \d 和 \D 大小写正好是取反 \s 和 \S 大小写取反 。。。。。 更多的大小写取反
-
量词啊!!!
-
所谓量词就是表示多少数量的词,从
0 - n
满足你花样的数量匹配的需求。
-
伴随量词而来的另一个问题,到底匹配多少次
'12345678'.replace(/\d{3, 6}/g, 'X'); // 谁能聊聊这个到底匹配了几个字符 悄悄告诉圣僧,正则默认采用的的是贪婪模式(正则就像贪食蛇一样尽可能多的匹配)
正则的 贪婪模式 和非贪婪模式 (因为
其伴随着量词而生
,所有总在量词后面,使用一个 ? 来区分
)'12345678'.replace(/\d{3,6}/g, 'X'); // X78 贪婪模式 '12345678'.replace(/\d{3,6}?/g, 'X'); // XX 78 非贪婪模式
-
-
边界类
边界类就是取字符的边界 (文档都应该有 上下左右留白,正则也是很有要面子的)
b -> boundary // 解释一下 b 代表的单词
3. 从这里开启新征程
-
分组 所谓分组就是将
组内的整体当做元字符
使用。(byron){3} // 分组将 byron 作为整体 (byron|capital) // 分组将 byron或者capital 作为整体 by(ron|cap)ital // 分组将 ron或者cap 作为整体
-
分组的引用 每个小小的分组其实都有一个默认的引用 (
拿啥引,拿钱引呗
)'2015-11-21'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1') // "21/11/2015" 看见没 $3 就表示 第三个分组(括号) 里面的 内容 $2 就表示 第二个分组(括号) 里面的 内容 $1 就表示 第一个分组(括号) 里面的 内容 这就是分组的引用
-
忽略分组 有些分组我们不想要怎么办??
(?:内容) 使用 ?: 就表示可以忽略该分组
比如我们想在写的乱七八糟的数据里面找日期并且换种显示方式 '2015-asdasd-11-21'.replace(/(\d{4})-(?:\w+)-(\d{2})-(\d{2})/, '$3/$2/$1'); // "21/11/2015"
有个小问题?
[]
中括号 表示或者的意思,而|
竖线 也表示或者的意思,这两者有何区别?
4. 来看看 正则表达式的匹配原理是什么
记住四个字: 前瞻 后顾
正则表达式的前瞻:
1,正则表达式是从文本头部向尾部开始解析,从文本尾部向文本前部,称为‘前’
2,前瞻就是在正则表达式匹配到规则时,向前检查是否符合断言。
所谓的前瞻就是在正则表达式匹配到某个字符的时候,往“尚未解析过的文本”预先看一下,看是不是符合/不符合匹配模式,
而后顾,就是在正则引擎已经匹配过的文本看看是不是符合/不符合匹配模式。符合和不符合特定匹配模式我们又称为肯定式匹配和否定式匹配。
反向/否定匹配称为断言不符合
本节课程基本没有实用性,大家了解就好!!!!!!
5. 看看真正的正则表达式强人是怎么炼成的 (实践证明全局和非全局是非常重要的)
-
正式表达式本质是个啥?是个对象呀(一帮叫做正则表达式对象)
是对象就应该有属性和方法,下面来看看 (五大三粗少一粗
就是五个属性两个方法
)- 属性 有下面五个
reg.global, reg.ignoreCase, reg.multiline 都是只读的正则属性
-
解释一下这个 lastIndex
与正则表达式相关的术语 :
当前表达式
+最后一个字符
+下一个字符
有的同学说我这个正则表达式结果不稳定呀, 这个 test 只有第一次完全正确,以后都是不确定的,这个怎么办? 其实就是 lasrIndex 在作怪,下面详细说明 var reg = /\w/g reg.test(a); // true reg.test(a); // false
-
正则表达式的方法
-
test
Reg 对象属性
表示 测试后面的字符是否能在前面的 test 中找到test 只是用于测试是否存在,不关系 lastIndex...一些详细信息
-
exec
RegExp.prototype.exec
正则更详细的信息在这里exec 后结果解析: 匹配到了文本 返回数组 若没有 匹配到的文本则返回null reg.index 表示匹配文本的第一个字符串 reg.input 表示被检索的字符串
exec 在全局和非全局 (有 g 和没有 g) 结果下有不一样的结果
非全局下
lastIndex == 0 (而且一直为零)
全局情况下
lastIndex 随着匹配的前瞻而变化
-
-
字符串的正则匹配方法 ** 四个大汉**
使用这四个方法进行匹配时,就算传入的参数不是正则,javascript 也会尽可能尝试将参数转为正则
-
String.prototype.search(reg/str/...);
特点:
方法返回第一个匹配结果的index,查找不到返回-1; 方法不执行全局匹配,它将忽略标志g, 总是从字符串的开始进行检索(总是从头开始查找)
-
String.prototype.match(reg/str/...)
特点:是否全局有区别 非全局情况下和 exec 的到的结果基本类似 result.index result ['匹配到的子字符串', '分组信息'] result.lastIndex (没有该属性) 全局情况下 匹配所有的匹配到的子字符串(是一个数组) result.lastIndex (没有该属性) result ['匹配到的子字符串1', '匹配到的子字符串2',.....] (没有分组信息)
-
String.prototype.split(reg/str/...)
特点: 将匹配到的字符作为分割符号 将字符串切成数组
-
String.prototype.replace('reg/str/...找谁)', '替换成的样子')
特点: 将找到的字符替换成设定的字符串
replace 送额外的福利啦
replace 需要替换的字符可以又一个函数的 callback 来承担 String.prototype.replace(reg, function(resultStr, group1, gruop2, index, sourceStr) {})
-
-
大家聊聊
str.match(reg)
和reg.exec(str)
分别有什么不同提示一下: 是否带有 g(全文搜索) 返回的结果(比如结果中都有神马?index, lastIndex ....)
-
几个常见的注意事项
-
^ 放在外面和放在 [] (中括号)里面是不一样的
^(135|136|177|180) // 放在外面的 ^ 表示以 某个字符开头的 [^135] // 放在 中括号里面表示取反,不包括这些字符
-
? 单独出现和放在 () (小括号中) 是不一样的
? 放在单独出现表示一个量词 // 表示 问号 前面的量词出现 零次或者一次 [123]? // 表示 1 或者 2 或者 3 ,三个数字最多出现一次 ? 放在小括号中 // 表示前瞻 后顾 负前瞻,负 后顾 前瞻: exp1(?=exp2) 查找exp2前面的exp1 后顾: (?<=exp2)exp1 查找exp2后面的exp1 负前瞻: exp1(?=exp2) 查找后面不是exp2的exp1 负后顾: (?<=exp2)exp1 查找前面不是exp2的exp1 可以发现,负前瞻、负后顾就是把前瞻、后顾中的"="改成了"!" 示例: (?<=博)客(?=园) // 表示只 匹配到 博客园 中的 客 字 (?<!博)客(?!园) // 表示只匹配其他字符串中的 客 字,不匹配 博客园 字符串中的客
-