正则表达式与字符串查找方法,JavaScript正则表达式学习笔记之一

首先提出一个问题:

图片 1

定义:正则用于规定在文本中检索的内容,它是对字符串执行模式匹配的强大工具

如何取得一个给定的字符串substr在另一个字符串str中出现的次数?

自从年前得空写了两篇文章之后就开始忙了,这一忙就是2个月😭。当时信誓旦旦说的定期写篇博客的计划也就泡汤了🤣,不过好在最近有空,顺便总结一下这两个月遇到的几个问题。第一个问题就是项目中用到了一些正则才发现之前被自己忽略的正则是时候补一补了。恰逢今天周六😎,就把自己学习JavaScript正则表达式的笔记整理成文,写了这篇关于正则表达式理论基础的文章,希望本文能对有需要的同学提供帮助。号外:本文相对基础,大神请忽略🙈。

RegExp(正则表达式) 对象的语法: new RegExp(pattern, attributes);

字符串匹配,第一想到的就是正则表达式,但我们最常使用的字面量来创建的正则表达式方式却无法传入变量,

一. 基本概念

  1. 正则表达式是用于匹配字符串中字符组合的模式。
    一种几乎可以在所有的程序设计语言里和所有的计算机平台上使用的文字处理工具。它可以用来查找(搜索)特定的信息,也可以用来查找并编辑(替换)特定的信息。

  2. 核心是匹配,匹配位置或者匹配字符。

  3. JavaScript 中,正则表达式也是对象。

  4. 这些模式被用于 RegExpexectest 方法, 以及 String
    matchreplacesearchsplit 方法。

  pattern为一个字符串或匹配规则 attributes为可选字符串,包含属性g、i
和 m

这时应该使用另一种创建正则表达式的方式:构造函数,如下

二. 创建正则表达式

  g:代表全局匹配 (继续往下匹配)

var reg = new RegExp(substr, "g");

2.1 正则表达式的创建可以有以下三种方法。

  i:代表不区分大小写匹配

其中第一个参数表示要匹配的字符串模式,因此可以传入变量,不需要加/
/,第二个参数是可选的标志字符串。

2.1.1 字面量

/pattern/flags

let reg1 = /jing ke tong xue/g;
console.log(reg1); // /jing ke tong xue/g

  m:代表多行匹配,只对^和$模式有用

可以传入变量了,再介绍个字符串基本包装类型的方法:match()

2.1.2 构造函数

new RegExp(pattern [, flags])

let reg2 = new RegExp('jing ke tong xue', 'g');
console.log(reg2); // /jing ke tong xue/g

定义正则表达式有两种形式:

语法为str.match(regExp),参数为一个正则表达式,若传的不是正则则会隐式转换,返回值为一个包含匹配结果的数组,如果没有匹配项,则返回null。

2.1.3 工厂符号

RegExp(pattern [, flags])

let reg3 = RegExp('jing ke tong xue', 'g');
console.log(reg3); // /jing ke tong xue/g

  构造函数方式: new RegExp(pattern, attributes);

另外,字符串的match方法与正则的exec()类似,返回匹配的详细信息;字符串的search方法与正则的test()类似,只是用来查看是否匹配。

2.2 字面量、构造函数、工厂符号在创建正则表达式中的异同

    例:var reg=new RegExp(“abc”,”g”);
构造函数中的正则可以是常量字符串或一个js变量

回到最初的问题,完整的程序如下:

2.2.1 共同点

三种方法都可以创建正则表达式,正则表达式的文本pattern为必须参数,标志符flagsg、i、m、y、u五个可选、可任意搭配参数。

  普通方式:/pattern/attributes(/正则/属性)

var str1 = "abctestctesqk1test23";
var str2 = "test";

function countSubstr(str, substr) {
  var reg = new RegExp(substr, "g");
  return str.match(reg) ? str.match(reg).length : 0;//若match返回不为null,则结果为true,输出match返回的数组(["test","test"])的长度
}
console.log(countSubstr(str1, str2));//输出2
2.2.2 不同点

构造函数和工厂符号除了相差一个new关键字外没有什么不同,但是不推荐工厂符号的形式创建正则表达式。下面主要说一下字面量和构造函数的形式创建正则表达式的不同之处。

  1. 当表达式被赋值时,字面量形式提供正则表达式的编译(compilation)状态,当正则表达式保持为常量时使用字面量。例如当你在循环中使用字面量构造一个正则表达式时,正则表达式不会在每一次迭代中都被重新编译(recompiled)

  2. 正则表达式对象的构造函数,如new RegExp('jing ke tong xue')提供了正则表达式运行时编译(runtime compilation)。如果你知道正则表达式模式将会改变,或者你事先不知道什么模式,而是从另一个来源获取,如用户输入,这些情况都可以使用构造函数。

  3. ECMAScript 6开始,当第一个参数为正则表达式而第二个标志参数存在时,new RegExp(/jing ke tong xue/, 'g')不再抛出==TypeError==
    (“当从其他正则表达式进行构造时不支持标志”)的异常,取而代之,将使用这些参数创建一个新的正则表达式。

  4. 字面量方式pattern中所有字符都是元字符,所以不能进行变量值的拼接。通过构造函数的方式pattern中所有字符都是字符串,是可以进行字符串拼接的,同时对于特殊字符也是需要转义的。

  • 字符串变量拼接

const name = 'jing ke';

// 字符串拼接不会成功
let reg1 = /" + name + " tong xue/g;
console.log(reg1); // /" + name + " tong xue/g

// 字符串拼接可以成功
let reg2 = new RegExp(name + ' tong xue', 'g');
console.log(reg2); // /jing ke tong xue/g
  • 特殊字符转义

const name = 'jing     ke';

// 匹配name,这里jing和ke之间可能有1个或多个空格
let reg1 = /jing\s+ke/g;
console.log(reg1); // /jing\s+ke/g
console.log(reg1.test(name)); // true

// 这里创建的正则表达式和字面量方式创建的结果并不一样
let reg2 = new RegExp('jing\s+ke', 'g');
console.log(reg2); // /jings+ke/g
console.log(reg2.test(name)); // false

// 这里我把reg3稍稍改造了一下,结果就和reg1一样了
let reg3 = new RegExp('jing\\s+ke', 'g');
console.log(reg3); // /jing\s+ke/g
console.log(reg3.test(name)); // true

再看一个特殊字符转义的例子

// 写一个正则表达式匹配反斜杠 \
const str = '\\'; // 这里str就是 \,反斜杠有特殊意义,下文介绍基本元字符会讲
// 字面量方式
let reg1 = /\\/g;
console.log(reg1); // /\\/g
console.log(reg1.test(str)); // true

// 为什么是4个反斜杠,详见下文元字符介绍。自己在控制台试试1个,2个,3个会报什么错
let reg2 = new RegExp('\\\\', 'g');
console.log(reg2); // /\\/g
console.log(reg2.test(str)); // true

    例:var reg=/abc/g; 普通方式中的正则必须是一个常量字符串

另外,对于变量的问题,不使用构造函数也可以解决,即使用eval():

三. 正则表达式中特殊字符

每个正则表达式都有一个 lastIndex
属性,用于记录上一次匹配结束的位置(索引值)。

var reg = "/" + substr + "/g";
reg = eval(reg);//不推荐!

3.1 标志字符

标志字符 含义
g 全局匹配,找到所有匹配,而不是在第一个匹配后停止。
i 忽略大小写。
m 多行,将开始和结束字符(^和$)视为在多行上工作(也就是,分别匹配每一行的开始和结束(由 \n 或 \r 分割),而不只是只匹配整个输入字符串的最开始和最末尾处。
u ES6新增,Unicode,将模式视为Unicode序列点的序列。
y ES6新增,粘性匹配,仅匹配目标字符串中此正则表达式的lastIndex属性指示的索引(并且不尝试从任何后续的索引匹配)。

获取 reg.lastIndex

但都知道不推荐使用eval()方法,所以还是推荐使用构造函数方法。

3.2 基本元字符

基本元字符 含义
. 匹配除了换行符之外的任何单个字符
\ 在非特殊字符之前的反斜杠表示下一个字符是特殊的,不能从字面上解释。例如,没有前\b通常匹配小写b,无论它们出现在哪里。如果加了\,这个字符变成了一个特殊意义的字符,反斜杠也可以将其后的特殊字符,转义为字面量。例如,模式 /a*/ 代表会匹配0个或者多个a。相反,模式 /a\*/*的特殊性移除,从而可以匹配像 a* 这样的字符串。
| 逻辑或操作符。
[…] 定义一个字符集合,匹配字符集合中的一个字符,在字符集合里面像 .\这些字符都表示其本身。
[^…] 对上面一个集合取非。
定义一个区间,例如[A-Z],其首尾字符在 ASCII 字符集里面。

设置 reg.lastIndex=0;

但还是有个问题,如果子字符串中含有正则表达式中所谓的元字符(即+*?^等),则无法正常匹配。

3.3 数量元字符

量词 含义
* 等价于{0,},表示出现任意次,可以不出现。
+ 等价于{1,},表示至少出现一次,上不封顶。
? 等价于{0, 1}表示出现一次或零次。
{m} 等价于{m, m},标志正好出现m次,不能多也不能少。
{m,} 表示至少出现 m 次,上不封顶。

量词后面加?可以实现惰性匹配,对应关系如下:

贪婪量词 惰性量词
* *?
+ +?
? ??
{m} {m}?
{m,} {m,}?

示例: var str=‘abcdeabfg’;

因为此时正则表达式是在字符串里的,\是字符串中的转义符,也是正则表达式中的转义符。那么只加一个\的话,只能说明在字符串中转义,而js需要进一步把普通字符串中的\变成正则表达式中的\,像是更深一则转化的意思,称为双重转义,这样\\以后的意思是正则表达式中的转义符(\)。

3.4 锚字符(位置元字符)

字符 含义
^ 单独使用匹配表达式的开始。匹配字符串的开头,在多行检索中,匹配一行的开头。
$ 匹配表达式的结束。匹配字符串的结尾,在多行检索中,匹配一行的结尾。
\b 匹配一个单词的边界,简而言之,就是位于字符\w和字符\W之间的位置,或位于字符\w和字符串的开头或结尾之间的位置(但需要注意的是在字符组内[\b]匹配的是退格符)。
\B 匹配非单词边界。
(?=p) 匹配 p 前面的位置。零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符。
(?!p) 匹配不是 p 前面的位置。零宽负向先行断言,要求接下来的字符不与p匹配。

    var reg=new RegExp(‘ab’,‘g’);

所以对于那些元字符如果不进行双重转义,则无法真正查找要找的那个字符。这个问题尚未解决,不过一般字符串查找也很少有这些特殊字符吧,可以先一用。

3.5 特殊元字符

字符 含义
\d 等价于[0-9],表示一位数字s。
\D 等价于[^0-9],表示一位非数字。除了ASCⅡ数字之外的任何字符。
\s 等价于[\t\v\n\r\f],表示空白符,包括空格,水平制表符(\t),垂直制表符(\v),换行符(\n),回车符(\r),换页符(\f)
\S 等价于[^\t\v\n\r\f],表示非空白符。
\w 等价于[0-9a-zA-Z],表示数字大小写字母和下划线。
\W 等价于[^0-9a-zA-Z],表示非单词字符。

         alert(reg.test(str));//true

以上这篇JavaScript
正则表达式与字符串查找方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

四. 正则表达式的一些属性

         alert(reg.lastIndex);//2

您可能感兴趣的文章:

  • js正则表达式之search方法讲解
  • String字符串匹配javascript
    正则表达式
  • Javascript字符串常用方法详解
  • 超全的js正则表达式整理笔记
  • ES6学习笔记之正则表达式和字符串正则方法分析

4.1 RegExp.lastIndex

  • lastIndex
    是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。

  • 只有正则表达式使用了表示全局检索的 “g” 标志时,该属性才会起作用。

如果 lastIndex 大于字符串的长度,则 regexp.testregexp.exec
将会匹配失败,然后 lastIndex 被设置为 0。

如果 lastIndex
等于字符串的长度,且该正则表达式匹配空字符串,则该正则表达式匹配从
lastIndex 开始的字符串。

如果 lastIndex 等于字符串的长度,且该正则表达式不匹配空字符串
,则该正则表达式不匹配字符串,lastIndex 被设置为 0。

否则,lastIndex 被设置为紧随最近一次成功匹配的下一个位置。

请看如下示例代码:

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue jing ke tong xue';
let reg = /jing ke tong xue/g;
// lastIndex从0开始
console.log(reg.lastIndex); // 0
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 16
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 33
// lastIndex可修改
reg.lastIndex = 0;
console.log(reg.lastIndex); // 0
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 16
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 33
console.log(reg.test(str)); // false
console.log(reg.lastIndex); // 50
console.log(reg.test(str));// true
console.log(reg.lastIndex); // 67
console.log(reg.test(str));// false
// 上一次匹配失败,lastIndex重置为0
console.log(reg.lastIndex); // 0
console.log(reg.test(str));// true

元字符

4.2 RegExp.prototype.global

  • global属性表明正则表达式是否使用了 “g” 标志。

  • global的值是布尔对象,如果使用了 “g”
    标志,则返回true;否则返回false。 “g”
    标志意味着正则表达式应该测试字符串中所有可能的匹配。

  • global是一个正则表达式实例的只读属性。RegExp.prototype.globalwritableenumerableconfigurable属性均为false,无法直接更改此属性。

请看如下示例代码:

let reg1 = /jing ke tong xue/;
console.log(reg1.global); // false.

let reg2 = /jing ke tong xue/g;
console.log(reg2.global); // true

\d : 匹配任意一个数字,0~9 中的任意一个

4.3 RegExp.prototype.ignoreCase

  • ignoreCase属性表明正则表达式是否使用了 “i” 标志。

  • ignoreCase的值是布尔对象,如果使用了”i”
    标志,则返回true;否则,返回false。”i”标志意味着在字符串进行匹配时,应该忽略大小写。

  • ignoreCase是正则表达式实例的只读属性。RegExp.prototype.ignoreCasewritableenumerableconfigurable属性均为false,无法直接更改此属性。

请看如下示例代码:

let reg1 = /jing ke tong xue/;
console.log(reg1.ignoreCase); // false.

let reg2 = /jing ke tong xue/i;
console.log(reg2.ignoreCase); // true

\s : 匹配任意一个空白字符

4.4 RegExp.prototype.multiline

  • multiline属性表明正则表达式是否使用了 “m” 标志。

  • multiline的值是布尔对象,如果使用了”m”
    标志,则返回true;否则,返回false。”m”
    标志意味着一个多行输入字符串被看作多行。

  • multiline是正则表达式实例的一个只读属性。RegExp.prototype.multilinewritableenumerableconfigurable属性均为false,无法直接更改此属性。

请看如下示例代码:

let reg1 = /jing ke tong xue/;
console.log(reg1.multiline); // false.

let reg2 = /jing ke tong xue/m;
console.log(reg2.multiline); // true

\b : 匹配一个单词边界,不匹配任何字符

4.5 RegExp.prototype.unicode

  • unicode属性表明正则表达式带有”u” 标志。

  • unicode的值是Boolean,并且如果使用了 “u”
    标志则为true;否则为false。”u”
    标志开启了多种Unicode相关的特性。使用 “u” 标志,任何Unicode
    代码点的转义都会被解释。

  • unicode是正则表达式独立实例的只读属性。RegExp.prototype.unicodewritableenumerable属性为falseconfigurable属性均为true,无法直接更改此属性。

请看如下示例代码:

let reg1 = /jing ke tong xue/;
console.log(reg1.unicode); // false.

let reg2 = /jing ke tong xue/u;
console.log(reg2.unicode); // true

再看如下示例代码:

// 定义一个四个字节的 UTF-16 编码的字符
const str = '\uD83D\uDC2A';

let reg1 = /^\uD83D/;
// ES5不支持四个字节的 UTF-16 编码,会将其识别为两个字符,故而输出 true
console.log(reg1.test(str)); // true

let reg2 = /^\uD83D/u;
// 加了u修饰符以后,ES6 就会识别其为一个字符,故而输出false
console.log(reg2.test(str)); // false

\w : 匹配任意一个字符( 字母、 数字、下划线 )

4.6 RegExp.prototype.sticky

  • sticky属性表明正则表达式带有”y” 标志。

  • sticky的值是 Boolean
    ,并且如果使用了”y”标志则为true;否则为false。”y”
    标志指示搜索是否具有粘性,仅从正则表达式的lastIndex
    属性表示的索引处为目标字符串匹配(并且不会尝试从后续索引匹配)。

  • sticky是正则表达式独立实例的只读属性。RegExp.prototype.stickywritableenumerable属性为falseconfigurable属性均为true,无法直接更改此属性。

请看如下示例代码:

let reg1 = /jing ke tong xue/;
console.log(reg1.sticky); // false.

let reg2 = /jing ke tong xue/y;
console.log(reg2.sticky); // true

再看如下示例代码:

const str = 'test jing ke tong xue test jing ke tong xue';

let reg1 = /jing ke tong xue/;
// 没有y标识符,lastIndex始终为0,但是reg1并不具有粘性,并不从lastIndex号为开始
console.log(reg1.lastIndex); // 0
console.log(reg1.test(str)); // true
reg1.lastIndex = 5;
console.log(reg1.lastIndex); // 5
console.log(reg1.test(str)); // true
// 由于没有y标识符,在正则表达式匹配之后,lastIndex又被重置为0
console.log(reg1.lastIndex); // 0
console.log(reg1.test(str)); // true

let reg2 = /jing ke tong xue/y;
// 第一次匹配将从0号位开始
console.log(reg2.lastIndex); // 0
console.log(reg2.test(str)); // false
// 第二次一次匹配将从5号位开始
reg2.lastIndex = 5;
console.log(reg2.lastIndex); // 5
console.log(reg2.test(str)); // true
// 下一次匹配将从21号位开始
console.log(reg2.lastIndex); // 21
console.log(reg2.test(str)); // false
// 上一次匹配失败,lastIndex重置为0;下一次匹配将从0号位开始
console.log(reg2.lastIndex); 

. : 匹配任意一个字符,除了换行符( \n )

4.7 RegExp.prototype.source

  • source
    属性返回一个值为当前正则表达式对象的模式文本的字符串。该字符串不会包含正则字面量两边的斜杠以及任何的标志字符。

请看如下示例代码:

let reg = /jing ke tong xue/gimuy;
console.log(reg.source); // jing ke tong xue
// source无法被修改,不会生效
reg.source = 'tong xue jing ke';
console.log(reg); // /jing ke tong xue/gimuy

\n : 查找换行符

4.8 RegExp.prototype.flags

  • flagsES6新增属性,返回一个由当前正则表达式对象的标志组成的字符串。

  • 标志以字母表顺序排序。(从左到右gimuy)。

  • flags是正则表达式独立实例的只读属性。RegExp.prototype.flagswritableenumerable属性为falseconfigurable属性均为true,无法直接更改此属性。

请看如下示例代码:

let reg = /jing ke tong xue/gimuy;
console.log(reg.flags); // jing ke tong xue
// flags无法被修改,不会生效
reg.flags = 'g';
console.log(reg); // /jing ke tong xue/gimuy

flags属性为ES6新增属性,ES6以前可用如下Polyfill。

if (RegExp.prototype.flags === undefined) {
  Object.defineProperty(RegExp.prototype, 'flags', {
    writable: false, // 默认为false,写上便于理解
    enumerable: false, // 默认为false,写上便于理解
    configurable: true,
    get: function() {
      return this.toString().match(/[gimuy]*$/)[0];
    }
  });
}

\u : 通常用来匹配汉字

五. 正则表达式的一些方法

表达式 “\d”,”\s”,”\b”,”\w”,对应的大写字母表示相反的意义

5.1 RegExp.prototype.test

  • 语法 reg.test(str)str:用来与正则表达式匹配的字符串。

  • test()
    方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。

  • 如果正则表达式与指定的字符串匹配 ,返回true,否则false

const str = 'jing ke tong xue';
let reg1 = /^jing/;
// 判断str是不是以jing开头
console.log(reg1.test(str)); // true

let reg2 = /^ke/;
// 判断str是不是以ke开头
console.log(reg2.test(str)); // fase

在设置有全局标志g的正则使用test方法。

如果正则表达式设置了全局标志,test方法的执行会改变正则表达式的
lastIndex 属性。连续的执行test方法,后续的执行将会从 lastIndex
处开始匹配字符串。如果 test 方法返回匹配失败 false,lastIndex
属性将会被重置为0。

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue';
let reg = /jing ke/g;

console.log(reg.lastIndex); // 0
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 7
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 24
console.log(reg.test(str)); // true
console.log(reg.lastIndex); // 41
console.log(reg.test(str)); // false
console.log(reg.lastIndex); // 0

如:\D 匹配所有的非数字字符;

5.2 RegExp.prototype.exec

  • 语法reg.exec(str)str:要匹配正则表达式的字符串。 exec()
    方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null

  • 如果匹配成功,exec()
    方法返回一个数组,并更新正则表达式对象的属性。返回的数组将完全匹配成功的文本作为第一项,将正则括号里匹配成功的作为数组填充到后面。

  • 如果匹配失败,exec() 方法返回 null

💥如果你只是需要第一个匹配结果,你可能想要使用 RegExp.exec() 。

💥如果你想要获得捕获组,并且设置了全局标志,你需要用
String.prototype.match() 。

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue';
let reg = /jing ke/g;

console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); // ["jing ke", index: 0, input: "jing ke tong xue jing ke tong xue jing ke tong xue", groups: undefined]
console.log(reg.lastIndex); // 7
console.log(reg.exec(str)); // ["jing ke", index: 17, input: "jing ke tong xue jing ke tong xue jing ke tong xue", groups: undefined]
console.log(reg.lastIndex); // 24
console.log(reg.exec(str)); // ["jing ke", index: 34, input: "jing ke tong xue jing ke tong xue jing ke tong xue", groups: undefined]
console.log(reg.lastIndex); // 41
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0

从上述代码看出,在使用exec时,经常需要配合使用while循环使用:

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue';
let reg = /jing ke/g;

let result;
// 当reg.exec(str)返回null时结束循环,与上面代码结果一致
while (result = reg.exec(str)) {
    console.log(`result: ${result}`, `\nindex: ${result.index}`, `\nlastIndex: ${reg.lastIndex}`, `\ninput: ${result.input}`);
}

// result: jing ke 
// index: 0 
// lastIndex: 7 
// input: jing ke tong xue jing ke tong xue jing ke tong xue
// index.html:132 result: jing ke 

// index: 17 
// lastIndex: 24 
// input: jing ke tong xue jing ke tong xue jing ke tong xue
// index.html:132 result: jing ke 

// index: 34 
// lastIndex: 41 
// input: jing ke tong xue jing ke tong xue jing ke tong xue

方括号的使用:

5.2 RegExp.prototype.toString

  • 语法reg.toString()

  • toString() 返回一个表示该正则表达式的字符串。

  • RegExp 对象覆盖了 Object 对象的 toString() 方法,并没有继承
    Object.prototype.toString()。对于 RegExp 对象,toString()
    方法返回一个该正则表达式的字符串形式,同时会将flags属性按照字母表顺序重排。

let reg = /jing ke tong xue/yguim;
console.log(reg.toString()); // /jing ke tong xue/gimuy

[abc] : 查找方括号之间的任何字符。

六. 4种适用于模式匹配的String方法

这里介绍的4种String方法只是和模式匹配相关的内容,与模式匹配不相关的内容下面并不会提及,如果想了解更多请移步这里。

[^abc] : 查找任何不在方括号之间的字符。

6.1 String.prototype.search

  • 语法str.search(regexp)

regexp:一个正则表达式(regular expression)对象。如果传入一个非正则表达式对象,则会使用
new RegExp(obj) 隐式地将其转换为正则表达式对象。

  • search() 方法执行正则表达式和
    String对象之间的一个搜索匹配。当你想要知道字符串中是否存在某个模式(pattern)时可使用
    search,类似于正则表达式的 test 方法。

  • 如果匹配成功,则 search()
    返回正则表达式在字符串中首次匹配项的索引。否则,返回 -1。

💥如果你需要知道一个字符串是否匹配一个正则表达式 RegExp ,可使用
search()

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue jing ke tong xue';
let reg = /jing ke tong xue/g;
console.log(str.search(reg)); // 0

// 由于条件判断的时候喜欢用true或false, 改造如下, 详情请自行学习JavaScript位(~)运算符
console.log(!!~str.search(reg)); // true

[0-9] : 查找任何从 0 至 9 的数字。

6.2 String.prototype.match

  • 语法str.match(regexp)

regexp:一个正则表达式对象。如果传入一个非正则表达式对象,则会隐式地使用
new RegExp(obj) 将其转换为一个 RegExp
。如果你未提供任何参数,直接使用 match()
,那么你会得到一个包含空字符串的 Array :[""]

  • 当一个字符串与一个正则表达式匹配时, match()
    方法检索匹配项。如果正则表达式不包含 g 标志,则 str.match()
    会返回和 RegExp.exec() 相同的结果。而且返回的 Array
    拥有一个额外的 input
    属性,该属性包含被解析的原始字符串。另外,还拥有一个 index
    属性,该属性表示匹配结果在原字符串中的索引(以0开始)。

  • 如果正则表达式包含 g 标志,则该方法返回一个 Array
    ,它包含所有匹配的子字符串而不是匹配对象。捕获组不会被返回(即不返回index属性和input属性)。如果没有匹配到,则返回
    null

在下例中,使用 match 查找 “March” 紧跟着 1
个或多个数值字符,再紧跟着一个逗号“,”,再紧跟着一个或多个空格,接着跟着4个数值字符。正则表达式包含
i 标志,因此大小写会被忽略。第二个包含 g 标志会进行全局匹配。

// 啊,在2018年3月31日的下午,诗性大发,赋诗两句😎
// 🙈一支穿云箭, 千军万马来相见🙈
const str = 'In March 31, 2018, An arrow through the clouds to meet thousands upon thousands of horses and soldiers, In March 31, 2018';
let reg1 = /In (march \d+, (\d{4}))/i;
let match1 = str.match(reg1);
console.log(match1);
// 以下是logs内容
// => [
// =>   "In March 31, 2018",
// =>   "March 31, 2018",
// =>   "2018",
// =>   index: 0,
// =>   input: "In March 31, 2018, An arrow through the clouds to meet thousands upon thousands of horses and soldiers.",
// =>   groups: undefined
// => ]

// 📒释疑📌
// "In March 31, 2018" 是整个匹配
// "March 31, 2018" 是被(March \d+, (\d*))捕获的内容
// "2018" 是被(\d{4}) 捕获的内容
// index: 0 匹配开始的索引
// input: ... 是被解析的原始字符串 

// 这个和上面的差别就是flags多了个g标识符
let reg2 = /In (march \d+, (\d{4}))/ig;
let match2 = str.match(reg2);
// 多了一个标识符,返回的结果是一个包含匹配字符的数组
console.log(match2); // ["In March 31, 2018", "In March 31, 2018"]

号外,match
方法除了支持正则表达式对象作为参数外,还支持非正则表达式对象作为参数。

// 这个例子就不给答案了,好记性不如烂笔头,有心的同学请在控制台输出结果查看区别😄
const str1 = "NaN means not a number. Infinity contains -Infinity and +Infinity in JavaScript.";
const str2 = "4 is 4, 10 is 10, 14 is 14, 40 is 40.";
const str3 = "The contract was declared null and void.";
console.log(str1.match("number"));
console.log(str1.match("NaN"));
console.log(str1.match(NaN));
console.log(str1.match("Infinity"));
console.log(str1.match(Infinity));
console.log(str1.match(+Infinity));
console.log(str1.match(-Infinity));
console.log(str2.match("10"));
console.log(str2.match(10));
console.log(str2.match("-10"));
console.log(str2.match(-10));
console.log(str2.match("+10"));
console.log(str2.match(+10));
console.log(str3.match("null"));
console.log(str3.match(null));

[a-z] : 查找任何从小写 a 到小写 z 的字符。

6.3 String.prototype.split

  • 语法str.split([separator[, limit]])

separator: 指定表示每个拆分应发生的点的字符串。separator
可以是一个字符串或正则表达式。
如果纯文本分隔符包含多个字符,则必须找到整个字符串来表示分割点。如果在str中省略或不出现分隔符,则返回的数组包含一个由整个字符串组成的元素。如果分隔符为空字符串,则将str原字符串中每个字符的数组形式返回。

limit: 一个整数,限定返回的分割片段数量。当提供此参数时,split
方法会在指定分隔符的每次出现时分割该字符串,但在限制条目已放入数组时停止。如果在达到指定限制之前达到字符串的末尾,它可能仍然包含少于限制的条目。新数组中不返回剩下的文本。

split
方法接受两个参数,返回一个数组。第一个是用来分割字符串的字符或者正则,如果是空字符串则会将元字符串中的每个字符以数组形式返回,第二个参数可选作为限制分割多少个字符,也是返回的数组的长度限制。有一个地方需要注意,用捕获括号的时候会将匹配结果也包含在返回的数组中。

const str = 'jing ke tong xue jing ke tong xue jing ke tong xue';
let reg1 = /\s/;
console.log(str.split(reg1));
// => ["jing", "ke", "tong", "xue", "jing", "ke", "tong", "xue", "jing", "ke", "tong", "xue"]
console.log(str.split(" "));
// => ["jing", "ke", "tong", "xue", "jing", "ke", "tong", "xue", "jing", "ke", "tong", "xue"]

let reg2 = /\s+(tong)\s+/;
console.log(str.split(reg2));
// => ["jing ke", "tong", "xue jing ke", "tong", "xue jing ke", "tong", "xue"]

let reg3 = /\s+tong\s+/;
console.log(str.split(reg3));
// => ["jing ke", "xue jing ke", "xue jing ke", "xue"]

console.log(str.split(' tong '));
// => ["jing ke", "xue jing ke", "xue jing ke", "xue"]

 

6.4 String.prototype.replace

该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。

在进行全局的搜索替换时,正则表达式需包含 g 标志。

  • 语法 str.replace(regexp|substr, newSubStr|function)

regexp (pattern): 一个RegExp
对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。

substr (pattern): 一个要被 newSubStr
替换的字符串。其被视为一整个字符串,而不是一个正则表达式。仅仅是第一个匹配会被替换。

newSubStr (replacement):
用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。参考下面的使用字符串作为参数。

function (replacement):
一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的指定一个函数作为参数。

replace方法接受两个参数,第一个是要被替换的文本,可以是正则也可以是字符串,如果是字符串的时候不会被转换成正则,而是作为检索的直接量文本。第二个是替换成的文本,可以是字符串或者函数,字符串可以使用一些特殊的变量来替代前面捕获到的子串。返回一个部分或全部匹配由替代模式所取代的新的字符串。

如果使用字符串作为参数时替换字符串可以插入下面的特殊变量名:

变量名 代表的值
$$ 插入一个 "$"。
$& 插入匹配的子串。
$` 插入当前匹配的子串左边的内容。
$’ 插入当前匹配的子串右边的内容。
$n 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。

如果是函数的话,当匹配执行后, 该函数就会执行。
函数的返回值作为替换字符串。另外要注意的是,
如果第一个参数是正则表达式, 并且其为全局匹配模式,
那么这个方法将被多次调用, 每次匹配都会被调用。

变量名 代表的值
match 匹配的子串。(对应于上述的$&。)
p1, p2, … 假如replace()方法的第一个参数是一个RegExp 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)
offset 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是“abcd”,匹配到的子字符串是“bc”,那么这个参数将是1)
string 被匹配的原字符串。
const str = '2018-03-31';
let reg = /^(\d{4})\D(\d{2})\D(\d{2})$/;
function replacer (match, p1, p2, p3, offset, string) {
    console.log([match, p1, p2, p3, offset, string]);
    return [p1, p2, p3].join('/')
}
console.log(str.replace(reg, replacer));

// => ["2018-03-31", "2018", "03", "31", 0, "2018-03-31"]
// => 2018/03/31

由于内容比较多,文章写的太长也不便于阅读,所以本篇至此结束。后面估计还有两篇完结,到时候补了再更。

  • 第一篇完结(就是本文): JavaScript正则表达式学习笔记(一) –
    理论基础
  • 第二篇待更:JavaScript正则表达式学习笔记(二) –
    打怪升级
  • 第三篇待更:JavaScript正则表达式学习笔记(三) – 终章

[A-Z] : 查找任何从大写 A 到大写 Z的字符。

量词的使用:

n+ : 匹配任何包含至少一个 n 的字符串。

n? : 匹配任何包含零个或一个 n 的字符串。

n* : 匹配任何包含零个或多个 n 的字符串。

n{X} : 匹配包含 X 个 n 的序列的字符串。

n{X,Y} : 匹配包含 X 到Y 个 n 的序列的字符串。

^n : 匹配任何开头为 n 的字符串。

n$ : 匹配任何结尾为 n 的字符串。

其他相关

| : 匹配左边或者右边

\ : 转义符 特殊标点符号,在前面加 \ 后,就代表该符号本身

^ 要匹配 “^” 字符本身,请使用 \^ ( ) 要匹配小括号本身,请使用 \( 和
\)

RegExp 对象的方法

   test:检索字符串中指定的值 返回 true 或 false reg.test(str);

  exec: 检索字符串返回查找结果的第一个值 reg.exec(str);

  

  compile: 该方法可以重编辑指定的正则表达式

    var reg=new RegExp(“13[4-9](\\d){8}”,”g”);
//重新编辑正则表达式 reg.compile(“13[0-3](\\d){8}”,”g”);

String 对象方法

  search:检索与正则表达式相匹配的值

    用法:str.search(reg); (返回索引值,无-1)

  match:返回所有正则表达式的匹配(加g)

     用法:str.match(reg); (返回数组)

  replace:替换与正则表达式匹配的子串

    用法:str.replace(reg,””);

  split:将字符串匹配的部分做分割(去除)

    用法:str.split(reg); (返回数组)