Javascript 正则02-正则表达式位置匹配攻略

javascript 专栏收录该内容
48 篇文章 0 订阅

正则表达式

正则表达式是匹配模式, 要么匹配字符,要么匹配位置

正则表达式位置匹配攻略

在使用环视的时候,

  • 位置确定了可以通过位置来匹配位置后面(一般es5就是后面)的字符

  • 字符确定了,就可以通过字符来匹配字符前面的位置

主要内容

  1. 什么是位置?
  2. 如何匹配位置
  3. 位置的特性
  4. 实例分析

1. 什么是位置?

位置是相邻两个字符之间的位置(当然包含两个边界)。

2. 如何匹配位置

在 ES5 中,共有 6 个锚字符(表示位置的字符):

^ , $ , \b , \B , (?=p) , (?!p)

2.1 ^ 和 $

^ (脱字符) 匹配开头,在多行匹配中匹配行开头

$ (美元符号) 匹配结尾,在多行匹配中匹配行结尾

比如我们把字符串的开头结尾用 “#” 替换 (位置是可以替换成字符的!

var result = 'hello'.replace(/^|$/g , '#');
console.log(result);
// #hello#

多行匹配的时候,二者是行的概念,需要我们注意:


var result = 'i\nlove\njavascript'.replace(/^|$/g,'#');

// #i
// love
// javascript#

var result = 'i\nlove\njavascript'.replace(/^|$/gm,'#');
console.log(result);

// #i#
// #love#
// #javascript#

2.2 \b 和 \B

\b 是单词边界, 具体就是 \w 和 \W 之间的位置,也包括: \w 和 ^ 之间的位置,也包括 $ 和 \w 之间的位置。

比如: 文件名为 [JS] Lesson_01.mp4 中的 \b


var result = '[JS] Lesson_01.mp4'.replace(/\b/g,'#');
console.log(result);

// [#JS#] #Lesson_01#.#mp4#

\B 就是 \b 的反面, 非单词边界。例如在字符串中所有位置中,扣掉\b 剩下的就是 \B 位置

var result = '[JS] Lesson_01.mp4'.replace(/\B/g,'#');
console.log(result);

// #[J#S]# L#e#s#s#o#n#_#0#1.m#p#4

2.3 (?=p) 和 (?!p)

(?=p),其中 p 是一个子模式,即 p 前面的位置

比如 (?=i) ,表示 字符 ‘i’ 前面的位置


var result = 'hello'.replace(/(?=l)/g,'#');
console.log(result);

// he#l#lo

而 (?!p) 是 (?=p) 的反面,比如


var result = 'hello'.replace(/(?!l)/g,'#');
console.log(result);

// #h#ell#o#

二者的学名: 正向先行断言 (positive lookahead) 和 负向先行断言( negative lookahead)

es6 中还支持: positive lookbehind 和 negative lookbehind

具体是: (?<=p) 和(?<!p)

也有的书上解释成环视,看看左边,看看右边

3. 位置的特性

对于位置可以理解为 空字符 ''

比如:

// hello 字符 等价于

// 'hello'
'h'+ ''+ 'l'+ ''+ 'l'+ '' + 'l' + 'o'

所以说如下写法是没有问题的

var result = /^^hello$$$$/.test('hello')
console.log(result);
// true

var result2 = /(?=he)^^he(?=\w)llo$\b\b$/.test('hello')
console.log(result2);

// true

也就是说 字符之间的位置可以写成多个(位置是空字符串,随便叠加没问题)

4. 相关案例

4.1 不匹配任何东西的正则

/.^/

4.2 数字千位分割表示法

比如 ‘12345678’ 变为 ‘12,345,678’

4.2.1 弄出最后一个逗号

var regexp = /(?=\d{3}$)/g;
var result = '12345678'.replace(regexp, ',');
console.log(result);

// 12345,678
4.2.2 弄出所有逗号
var regexp = /(?=(\d{3})+$)/g;
var result = '12345678'.replace(regexp,',');
console.log(result);

// 12,345,678
4.2.3 验证案例

var result = '123456789'.replace(/(?=(\d{3})+$)/g,',')
console.log(result);

// ,123,456,789

// 修改后

var result = '123456789'.replace(/(?!^)(?=(\d{3})+$)/g,',')
console.log(result);

// 123,456,789
4.2.4 支持其他形式

'12345678 123456789' 替换成 '12,345,678 123,456,789'

var regexp = /(?!\b)(?=(\d{3})+\b)/g;
var result = '12345678 123456789'.replace(regexp, ',');
console.log(result);

// 12,345,678 123,456,789

其中 (?!\b) 可以理解为: 要求当前是一个位置,但不是 \b 前面的位置, 其实说的就是 \B

最终: /\B(?=(\d{3})+\b)/g

4.3 验证密码

要求: 密码长度 6-12, 有数字, 小写字符, 大写字母组成,但是必须至少是包含两种字符

分析:

  • 密码长度: x{6,12}
  • \d , [a-Z]
  • \d a , \d A , a A , \d a A

分析没错,写法错了, [\da-z]{6,12} 怎么保证 \d 被选中

var regexp = /^([\da-z]{6,12}|[\dA-Z]{6,12}|[A-z]{6,12}|[A-z\d]{6,12})$/g
4.3.1

不考虑至少 包含两种字符这一条件:var reg = /^[\dA-z]{6,12}$/

4.3.2 判断是否包含某一种字符

我们可以使用 (?=.*[0-9]) 来要求必须包含数字

正则变为: var reg = /(?=.*[0-9])^[\dA-z]{6,12}$/

这个体现了 锚字符随便放,0-9字符前面是任意字符,所以 0-9 必须含有

4.3.3 同时包含具体两种字符

比如同时包含数字和小写字母, 可以用 (?=.*[0-9])(?=.*[a-z])

正则变成: var reg = /(?=.*[0-9])(?=.*[a-z])^[\dA-z]{6,12}$/

4.3.4 解答

原题可以等价变换为:

  1. 同时包含数字和小写字母
  2. 同时包含数字和大写字母
  3. 同时包含小写字母和大写字母
  4. 同时包含数字,小写字母,大写字母

以上四种情况是或的关系(实际上可以不用第4条)

// 首先这是错误写法
var reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[A-z]))^[\dA-z]$/;

// 这是正确写法
var reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6,12}$/

// 这样缩写也没错
var reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[\dA-z]{6,12}$/

本题中有一种写法 需要注意下 (?=.*[A-z])(?=.*[a-z])(?=.*[A-Z]) 是不同的写法

(?=.*[A-z]) 表示 必须包含 A-z 之一

(?=.*[a-z])(?=.*[A-Z]) 表示 大小写同时包含

4.3.5 解惑

对于这个正则 :/(?=.*[0-9])^[\dA-z])$/,只需要明白 (?=.*\d)^ 即可。

分开来看就是 (?=.*[0-9]) 和 ^, 表示开头前面还有位置当然也是开头,即同一个位置,类比空字符)

(?=.*[0-9]) 表示该位置后面的字符匹配 .*[0-9],即有任何多个任意字符后面跟随数字(这里表示匹配子串的前面位置,也可以理解为这个位置后面是匹配子串),该位置后面的字符必须包含个数字

##### 4.3.6 另一种解法

“至少包含两种字符”意思就是说,不能全部是数字,不能全部是小写字母,不能全部是大写字母, 使用 (?!p)

要求不能全是 数字:var reg = /(?!^[0-9]{6,12}$)^[0-9A-Za-z]{6,12}$/;

最终答案:

var reg = /((?!^[0-9]{6,12}$)|(?!^[A-Z]{6,12})|(?!^[a-z]{6,12}))^[0-9A-Za-z]{6,12}$/;
reg.test('AEFSD123123');
  • 1
    点赞
  • 2
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值