思维导图 JavaScript 正则表达式之位置匹配

位置,也称之为 锚,是相邻字符之间的位置;实际上可以理解为一个空字符;如图所示,箭头所指就是位置

 

 那么该如何匹配位置呢?

在 ES5 中,共有 6 个锚:

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

其可视化表现形式如下图所示:

 思维导图:

案例分析:

案例一:不匹配任何东西 

/// 写一个正则,不匹配任何东西

let regex = /.^/
console.log( 'test word'.match(regex) )
// => null

 案例二:写一个正则,将给定的数字使用千位分隔符表示

/// 写一个正则,将给定的数字使用千位分隔符表示
/// 12345678 => 12,345,678

let string = "12345678"

/// 1, 整出最后一个逗号,即结尾三个数字前面加逗号
let regex = /(?=\d{3}$)/g
console.log( string.replace(regex, ',') )
// => 12345,678

/// 2, 弄出所有的逗号;也就是 \d{3} 匹配的目标字符串至少要出现一次
regex = /(?=(\d{3})+$)/g
console.log( string.replace(regex, ',') )
// => 12,345,678

/// 3, 使用 3 的倍数个数字长度匹配下看看效果
let str = "123456789"
console.log( str.replace(regex, ',') )
// => ,123,456,789   
// Ooops! 该死的,开头多了一个逗号,所以需要不能匹配开头位置

/// 4, (?!^) 就可以匹配不是开头的位置
regex = /(?!^)(?=(\d{3})+$)/g
console.log( str.replace(regex, ',') )
// => 123,456,789
// Good! 完美解决!

/// 5, "12345678  123456789" => "12,345,678  123,456,789"
console.log( "12345678  123456789".replace(regex, ',') )
// => 12345678  ,123,456,789
// Ooops! 竟然不行,那么问题在哪呢?因为存在空格,当匹配到空格位置的时候,便终止了
// 有什么办法没呢?
// 开玩笑,必须有啊!位置匹配不是可以有单词边界匹配 \b ,通过这个可以匹配 \w 与 \W 之间的位置 ...

regex = /(?!\b)(?=(\d{3})+\b)/g
console.log( "12345678  123456789".replace(regex, ',') )
// => 12,345,678  123,456,789
// Nice! 与期待的结果一致;那么是否还有可以优化的地方?
// 没错,有的;(?!\b) 这个实际上就是 \b 的取反,这不就是 \B 么?

regex = /\B(?=(\d{3})+\b)/g
console.log( "12345678  123456789".replace(regex, ',') )
// => 12,345,678  123,456,789

/// 应用场景
/// 千分符表示法最常见的应用就是货币格式化
/// 栗子:8888 => ¥ 8888.00

const formatRMB = num => {
    return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ',').replace(/^/, '¥ ')
}
console.log( formatRMB(8888) )
// => "¥ 8,888.00"

 案例三:密码验证问题

/// 密码验证问题
/// 密码长度 6-12 位,由数字、小写字符、大写字母,以及下划线 _ 组成,但必须包含至少 2 种字符

/// 分析:
/// 1, 密码长度 6-12 位,包含数字、小写字母、大写字母、下划线
let regex = /^[0-9a-zA-Z_]{6,12}$/

/// 2, 必须包含至少 2 种字符;先考虑必须包含数字
regex = /(?=.*[0-9])^[0-9a-zA-Z_]{6,12}$/
console.log( regex.test('_abcdefABC') )  // => false
console.log( regex.test('_abcdefABC12') )   // => true
/// (?=.*[0-9])   ?=.* 匹配到空字符,即位置,空字符后面需要有一个数字 => 必须包含数字

/// 3, 必须包含至少 2 种字符
/// 3.1 同时包含数字和小写字母
regex = /(?=.*[0-9])(?=.*[a-z])^[0-9a-zA-Z_]{6,12}$/

/// 3.1 同时包含数字和大写字母或下划线 (这里将下划线与大写字母放到一起了)
regex = /(?=.*[0-9])(?=.*[A-Z_])^[0-9a-zA-Z_]{6,12}$/

/// 3.2 同时包含小写字母和大写字母
regex = /(?=.*[a-z])(?=.*[A-Z])^[0-9a-zA-Z_]{6,12}$/

/// 综合起来
regex = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z_])|(?=.*[a-z])(?=.*[A-Z_]))^[0-9a-zA-Z_]{6,12}$/

console.log( regex.test('12345678') )   // => false
console.log( regex.test('abcdefg') )    // => false
console.log( regex.test('ABCDEFG') )    // => false
console.log( regex.test('ab12345') )    // => true
console.log( regex.test('AB1234HI') )   // => true
console.log( regex.test('ABC_EFG') )    // => false
console.log( regex.test('abc_edf') )    // => true
console.log( regex.test('abcdEFG12') )  // => true

console.log("===============================================")


/// 另一种思路:
/// 至少包含两种字符 => 不能全部都是数字,也不能全是小写字母,也不能全是大写字母或下划线
/// 先看不能全是数字该怎么办?
/// (?!^[0-9]{6,12}$) 如此便可,意思就是匹配位置后面不能是数字
regex = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z_]{6,12}$)^[0-9a-zA-Z_]{6,12}$/

console.log( regex.test('12345678') )   // => false
console.log( regex.test('abcdefg') )    // => false
console.log( regex.test('ABCDEFG') )    // => false
console.log( regex.test('ab12345') )    // => true
console.log( regex.test('AB1234HI') )   // => true
console.log( regex.test('ABC_EFG') )    // => false
console.log( regex.test('abc_edf') )    // => true
console.log( regex.test('abcdEFG12') )  // => true

代码仓库地址

案例源代码地址

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值