当前位置: 首页 > news >正文

JavaScript正则表达式学习笔记(一)

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

一. 基本概念

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

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

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

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

二. 创建正则表达式

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

2.1.1 字面量

/pattern/flags

let reg1 = /jing ke tong xue/g;
console.log(reg1); // /jing ke tong xue/g
复制代码
2.1.2 构造函数

new RegExp(pattern [, flags])

let reg2 = new RegExp('jing ke tong xue', 'g');
console.log(reg2); // /jing ke tong xue/g
复制代码
2.1.3 工厂符号

RegExp(pattern [, flags])

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

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

2.2.1 共同点

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

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
复制代码

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

3.1 标志字符

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

3.2 基本元字符

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

3.3 数量元字符

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

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

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

3.4 锚字符(位置元字符)

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

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],表示非单词字符。

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

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
复制代码

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
复制代码

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
复制代码

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
复制代码

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); 
复制代码

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
复制代码

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];
    }
  });
}
复制代码

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

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
复制代码

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
复制代码

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

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

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
复制代码

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));
复制代码

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正则表达式学习笔记(三) - 终章

相关文章:

  • 转载:ORA-12516 “TNS监听程序找不到符合协议堆栈要求的可用处理程序” 解决方案...
  • 深入浅出MyBatis:反射和动态代理
  • 阿里云服务器 从0 配置Node Nginx 免密ssh 等 环境实现 pm2一键线上部署
  • C# 谁改了我的代码 使用 Resharper 快速做适配器
  • 学不好Linux?我们分析看看正确的学习方法是什么
  • openssl的应用及创建CA
  • 基于zookeeper的高可用Hadoop HA集群安装
  • 归并排序的相关用法
  • 前端js -- this指向总结。
  • 理解Java集合(三)Map : HashMap/SortedMap/TreeMap
  • java io流
  • Heap Dump (heap=dump)
  • 配置Etcd集群和TLS认证
  • 学习最重要是方法,管理最重要是高度
  • git分支管理和工作流规范:不同场景细化和演示
  • ES10 特性的完整指南
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • javascript 哈希表
  • Java程序员幽默爆笑锦集
  • springMvc学习笔记(2)
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 机器学习中为什么要做归一化normalization
  • 浅谈Golang中select的用法
  • 我从编程教室毕业
  • 树莓派用上kodexplorer也能玩成私有网盘
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • # include “ “ 和 # include < >两者的区别
  • (day 12)JavaScript学习笔记(数组3)
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (笔试题)分解质因式
  • (第二周)效能测试
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (三)uboot源码分析
  • (十五)使用Nexus创建Maven私服
  • (算法)Game
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • **PHP分步表单提交思路(分页表单提交)
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET Core中Emit的使用
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 中viewstate的原理和使用
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • /etc/fstab 只读无法修改的解决办法
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • []利用定点式具实现:文件读取,完成不同进制之间的