文章首发于sau交流学习社区

一、前言

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

其实在开发中很少用到匹配位置,本篇文章主要包含:

二、什么是位置

位置:相邻字符之间的位置。

三、如何匹配位置

在ES5中,共有6个锚:^, $, \b, \B, (?=p), (?!p)

可视化形式:

RegExp:/^$\b\B(?=a)(?!b)/g

 

3.1 ^和$

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

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

比如:我们把字符串的开头和结尾用#替换(位置可以替换成字符的):

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

多行匹配模式(有修饰符m)时,二者是行的概念,我们需要注意:

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

3.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#"

首先,我们知道\w是字符组[0-9a-zA-Z]的简写,即使字母数字或者下划线中任何一个字符。而\W是字符组[^0-9a-zA-Z]的简写,即\W是\w以外的任何一个字符。

我们再来看#是怎么来的:

第 1 个,两边字符是 "[" 与 "J",是 \W 与 \w 之间的位置。

第 2 个,两边字符是 "S" 与 "]",也就是 \w 与 \W 之间的位置。

第 3 个,两边字符是空格与 "L",也就是 \W 与 \w 之间的位置。

第 4 个,两边字符是 "1" 与 ".",也就是 \w 与 \W 之间的位置。

第 5 个,两边字符是 "." 与 "m",也就是 \W 与 \w之间的位置。

第 6 个,位于结尾,前面的字符 "4" 是 \w,即 \w 与 $ 之间的位置。

知道了\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"

3.3 (?=p) 和 (?!p)

(?=p)其中p是一个子模式,即p前面的位置(该位置后面的字符要匹配p)

比如:(?=e),表示的是e字符前面的位置;

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。

中文翻译分别是正向先行断言负向先行断言

ES5 之后的版本,会支持 positive lookbehind 和 negative lookbehind。

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

四、位置特性

对于位置的理解,我们可以累计额成空字符""。

比如"hello"字符串等价于如下形式:

"hello" == "" + "h" + "" + "e" + "" + "l" + "" + "l" + "" + "o" + "";

也等价于

"hello" == "" + "" + "hello"

因此,把 /^hello$/ 写成 /^^hello$$$/,是没有任何问题的:

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

也就是说,字符之间的位置,可以写成多个。

注:把位置理解空字符,是对位置非常有效的理解方式

五、相关案例

5.1不匹配任何东西的正则

/.^/

正则要求只有一个字符,但是该字符后面是开头,而这样的字符串是不存在的。

5.2数字的千分位分隔符表示法

比如吧12345678,变成12,345,678。

分析:那就是需要把相应的位置替换成","

5.2.1弄出来最后一个逗号

正则:/(?=\d{3}$)/

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

其中(?=\d{3}$)匹配\d{3}$前面的位置。而\d{3}$匹配的是目标字符串最后那3为数字。

5.2.2弄出来多有逗号

因为逗号的出现的位置,要求后边3个数字一组,也就是\d{3}至少出现1次。

可以使用量词 + :

var result = "12345678".replace(/(?=(\d{3})+$)/g, ',')
console.log(result);
// 12,345,678

5.2.3匹配其余案例

写完正则后,是需要举个别案例来验证的,就会发现问题:

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

上面的正则,仅仅是表示把从结尾向前数,一旦是3的倍数买酒吧前面的位置替换为逗号。

还需要要求:匹配的这个位置不能是开头。

我们知道开头的匹配是使用^,但是不是开头怎么整?

使用(?!^)

var regex = /(?!^)(?=(\d{3})+$)/g;
var result = "12345678".replace(regex, ',')
console.log(result);
// "12,345,678"
result = "123456789".replace(regex, ',');
console.log(result);
// "123,456,789"

5.2.4支持其他形式

如果要把 "12345678 123456789" 替换成 "12,345,678 123,456,789"。

此时我们需要修改正则,把里面的开头 ^ 和结尾 $,修改成 \b:

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

其中(?!\b)怎么理解?

要求是当前的一个位置,但不是\b前面的位置,其实(?!\b)说的是\B。

因此最终正则变成了:/\B(?=(\d{3})+\b)/g。

可视化形式:

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

5.2.5货币格式化

千分符表示法一个常见的应用就是货币格式化。

把这个字符串:

1888

格式化:

$ 1888.00

实现:

function format (num) {
return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ",").replace(/^/, "$ ");
};
console.log( format(1888) );
// "$ 1,888.00"

5.3验证密码的问题

密码长度6-12,由数字,小写字母,大写字母组成,但必须至少包括2种字符。

写成多个正则来判断,比较容易,但是要写成一个正则就比较困难。

来看看我们对于位置的理解是否深刻。

5.3.1简化

暂时不考虑"必须至少包含2种字符"这个条件,可以容易写出:

var regex = /^[0-9A-Za-z]{6,12}$/;

5.3.2判断是否包含有某一种字符

假设,要求我们必须包含数字,怎么整?此时我们可以使用(?=.*[0-9])来实现。

正则变成:

var regex = /(?=.*[0-9])^[0-9A-Za-z]{6,12}$/;

5.3.3同时包含具体两种字符

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

正则变成:

var regex = /(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/;

5.3.3具体实现

把原题变成下列几种情况:

1、同时包含数字和小写字母;

2、同时包含数字和大写字母;

3、同时包含小写字母和大写字母;

4、同时包含数字,小写字母和大写字母。

以上的4中情况是的关系(实际上,第四条可以不用)。

最终答案:

var regex = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[AZ]))^[
0-9A-Za-z]{6,12}$/;
console.log( regex.test("1234567") ); // false 全是数字
console.log( regex.test("abcdef") ); // false 全是小写字母
console.log( regex.test("ABCDEFGH") ); // false 全是大写字母
console.log( regex.test("ab23C") ); // false 不足6位
console.log( regex.test("ABCDEF234") ); // true 大写字母和数字
console.log( regex.test("abcdEF234") ); // true 三者都有

可视化形式:

RegExp:/((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[AZ]))^[ 0-9A-Za-z]{6,12}$/

分析:

上面正则看起来好复杂,只需要理解第二步,/(?=.*[0-9])^[0-9A-Za-z]{6,12}$/;

对于这个正则,我们需要明白(?=.*[0-9])^这个;

分开来看就是(?=.*[0-9]) 和 ^。

表示开头前面还有个位置(当然也是开头,即同一个位置,想想之前的空字符类比)。

(?=.*[0-9]) 表示该位置后面的字符匹配。

.*[0-9],即,有任何多个任意字符,后面再跟个数字。

翻译成大白话,就是接下来的字符,必须包含个数字。

5.3.4另外一种解法

“至少包含两种字符”的意思就是说,不能全部都是数字,也不能全部都是小写字母,也不能全部都是大写字母。

那么要求“不能全部都是数字”,怎么做呢? (?!p) 出马!

对应的正则:

var regex = /(?!^[0-9]{6,12}$)^[0-9A-Za-z]{6,12}$/;

三种“都不能”呢?

最终答案是:

var regex = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;
console.log( regex.test("1234567") ); // false 全是数字
console.log( regex.test("abcdef") ); // false 全是小写字母
console.log( regex.test("ABCDEFGH") ); // false 全是大写字母
console.log( regex.test("ab23C") ); // false 不足6位
console.log( regex.test("ABCDEF234") ); // true 大写字母和数字
console.log( regex.test("abcdEF234") ); // true 三者都有

可视化形式:

RegExp:/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;

javascript正则表达式学习(二)--位置匹配的更多相关文章

  1. JavaScript正则表达式学习笔记(二) - 打怪升级

    本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...

  2. javascript正则表达式 - 学习笔记

    JavaScript 正则表达式 学习笔记 标签(空格分隔): 基础 JavaScript 正则表达式是用于匹配字符串中字符组合的模式.在javascript中,正则表达式也是对象.这些模式被用于Re ...

  3. JavaScript正则表达式(二)

    定义 JavaScript种正则表达式有两种定义方式,定义一个匹配类似 <%XXX%> 的字符串 1. 构造函数 var reg=new RegExp('<%[^%>]+%&g ...

  4. javascript 正则表达式学习教程

    正则表达式 就是用某种模式去匹配一类字串的一个公式 RegExp 对象表示正则表达式 Regular Expression 正则表达式是很多程序设计语法都支持的 //①隐式创建 var regexp ...

  5. javascript 正则表达式学习

    正则表达式 正则表达式,一个描述字符模式的对象.javascript的RegExp类表示正则表达式,String和RegExp都定义了方法,后者使用正则表达式进行强大的模式和匹配与替换功能. -- f ...

  6. JavaScript:正则表达式 前瞻 找位置

    js中全部都是顺序环视 顺序环视匹配过程 对于顺序肯定环视(?=Expression)来说,当子表达式Expression匹配成功时,(?=Expression)匹配成功,并报告(?=Expressi ...

  7. 初学JavaScript正则表达式(十二)

    text / exec方法 text() var reg1 = /\w/; var reg2 = /\w/g; reg1.test('a') === true reg2.test('a') === t ...

  8. JavaScript基础学习(二)—JavaScript基本概念

    一.语法 1.区分大小写     JavaScript是一种弱类型的脚本语言.它区分大小写,变量名test与Test表示两个完全不同的变量.   2.标识符      所谓标识符就是变量.函数.属性的 ...

  9. JavaScript 正则表达式学习笔记

    定义规则让计算机去处理字符串正则表达式写法: //第一种 var reg = new RegExp('ab'); //第二种 var reg = /ab/; 量词:{} [a-z] 从小写a-z [A ...

随机推荐

  1. springAOP之代理

    AOP是指面向切面编程. 在学习AOP之前先来了解一下代理,因为传说中的AOP其实也对代理的一种应用. 首先来看这样一段代码: public interface Hello { void say(St ...

  2. Python 基础【二】 上

    一.python语言分类 1. C python   c语言的python版本 官方推荐 使用C语言实现,使用最为广泛,CPython实现会将源文件(py文件)转换成字节码文件(pyc文件),然后运行 ...

  3. java中new关键字和newInstance()方法的区别

    1> new是一个关键字,可以说是一个指令: newInstance()是一个方法,Class对象的一个方法. 2> new主要作用是在内存中生成一个实例,而这个类可以没有提前加载到内从中 ...

  4. HTTP协议简单记录

    http协议的格式 1. 首行 2. 头 3. 空行 4. 体 http请求头 #Referer 请求来自哪里,如果是在http://www.baidu.com上点击链接发出的请求,那么Referer ...

  5. python logging method 02

    基本用法 下面的代码展示了logging最基本的用法.     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...

  6. Windows 安装 Vue

    引言 在公司 linux 环境下安装不顺利,回家在 windows 下操作感觉到一种幸福 nginx 先安装了 nginx,其实跟 vue 没关系,只是打算用它做 web 服务,此处略过 nginx ...

  7. 第五章——支持向量机(Support Vector Machines)

    svm可用于线性或非线性分类.回归.甚至异常检测. svm尤其适用于中小数据集的复杂分类问题. 5.1 Linear SVM Classification svm对feature scales敏感,如 ...

  8. 你不知道的JavaScript--Item15 prototype原型和原型链详解

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  9. mongoDB的安装及基本使用

    1.mongoDB简介 1.1 NoSQL数据库 数据库:进行高效的.有规则的进行数据持久化存储的软件 NoSQL数据库:Not only sql,指代非关系型数据库 优点:高可扩展性.分布式计算.低 ...

  10. QM4_Probability

    Basic Concepts Probability concepts Terms Random variable A quantity whose possible values are uncer ...