# 正则表达式

正则表达式是一种文本匹配的模式

# 1. RegExp 对象

在 JavaScript 中,有两种创建正则表达式的方式,它们分别是

var regexp = new RegExp('xyz');
var regexp = /xyz/;

# 1.1 实例属性

  • RegExp.prototype.ignoreCase:只读,返回布尔值,表示是否具有忽略大小写修饰符i

  • RegExp.prototype.global:只读,返回布尔值,表示是否具有全局匹配修饰符g

  • RegExp.prototype.multiline:只读,返回布尔值,表示是否具有多行匹配修饰符m

  • RegExp.prototype.source:只读,返回正则表达式的字符串形式,不包括修饰符

  • RegExp.prototype.flags:只读,返回字符串,表示正则表达式的匹配模式,按照字母顺序排序,可能的值:gimsuy

  • RegExp.prototype.lastIndex:可读写,表示下一次匹配开始的位置,可以通过手动设置属性来设置匹配的起始位置,只对同一个正则表达式生效

# 1.2 实例方法

# 1.2.1 RegExp.prototype.test()

从正则表达式的lastIndex属性位置开始搜索字符串,如果找到匹配的值,返回true,否则返回false

如果正则表达式含有g修饰符,并且匹配成功,正则表达式的lastIndex属性会随之改变为下一次开始匹配的位置

var reg = /xyz/g;
var str = 'abcdxyzfgxyz';
while(reg.test(str)) {
  console.log(reg.lastIndex)
}
// 7
// 12

# 1.2.2 RegExp.prototype.exec()

用正则表达式去匹配字符串,如果匹配成功,则返回一个数组,否则返回null

如果正则表达式含有(),表示组匹配,数组成员为匹配成功的子字符串,第一个成员为匹配整个正则表达式的字符串,第二个位匹配第一对()规则的字符串,以此类推。

返回的数组还包含以下两个属性:

  • index:整个正则表达式匹配字符串的起始位置
  • input:原始字符串
var reg = /xy(z)/g;
var str = 'abcxyzfdgxyz';

while(true) {
  const match = reg.exec(str);
  console.log(match);
  if(!match) break;
}
// (2) ["xyz", "z", index: 4, input: "abcdxyzfgxyz", groups: undefined]
// (2) ["xyz", "z", index: 9, input: "abcdxyzfgxyz", groups: undefined]
// null

# 2. 字符串中使用正则表达式的实例方法

  • String.prototype.match():匹配字符串
  • String.prototype.search():搜索字符串
  • String.prototype.replace():替换字符串
  • String.prototype.split():分割字符串

上面几个方法都可以接受正则表达式作为参数字符串,每次匹配都是从0开始,手动设置正则表达式的lastIndex属性无效

# 2.1 String.prototype.match()

接受一个正则表达式作为参数,返回一个数组,成员时匹配成功的子字符串,如果没有匹配成功null

  • 当正则表达式没有带有g修饰符的时候,执行的结果和RegExp.prototype.exec()结果一致
  • 当正则表达式带有g修饰符的时候,返回所有匹配成功的子字符串
var reg = /xyz/;
var reg2 = /xyz/g;
var str = 'abcxyzabcxyz';

str.match(reg);
// ["xyz", index: 3, input: "abcxyzabcxyz", groups: undefined]
str.match(reg2);
// ["xyz", "xyz"]

接受一个正则表达式作为参数,返回第一个匹配字符串在原字符串中的位置,如果没有匹配成功,返回-1

var reg = /x/;
var str = 'abxcxd';
str.search(reg);
// 2

# 2.3 String.prototype.replace()

接受两个参数,第一个为正则表达式,第二个位替换的字符串,如果正则表达式带有g修饰符,则替换所有满足条件的子字符串,如果没有,则替换第一个满足条件的子字符串

var reg = /x/g;
var str = 'abxcxd';
str.replace(reg, '0');
// "ab0c0d"

# 2.4 String.prototype.split()

按照正则规则将原字符串分割成数组

接受两个参数,第一个位正则表达式,第二个位返回数组的最大长度,可以省略,返回一个数组。

var reg = /x/;
var str = 'abxcxd';
str.split(reg);
// (3) ["ab", "c", "d"]

# 3.正则表达式规则

# 3.1 字面量字符

在正则表达式中,某个字符只表示它字面的含义,比如/z/,/a/分别匹配 a 和 b,就叫他字面量字符

# 3.2 元字符

具有特殊含义的字符,主要有

  • .:点字符,匹配除开回车 (\r)、换行 (\n)、行分割符 (\u2028) 和段分割符 (\u2029) 之外任意一个字符
  • ^:开始位置字符,表示匹配字符串开始
  • $:结束为止字符,表示匹配字符串结束
  • |:选择字符,表示或的关系
/^a.(b|c)d$/.test('abd'); // false
/^a.(b|c)d$/.test('accd'); // true
/^a.(b|c)d$/.test('accdb'); // false

# 3.3 转义符\

正则表达式中有一些特殊含义的元字符,如果要表达他们本身,则需要在字符前加上\进行转义

/\+/.test('a+b'); // true

# 3.4 特殊字符

正则表达式为一些不能打印的字符,提供了一些表达方法

  • [\b]匹配退格键,不要与\b混淆
  • \n匹配换行键
  • \r匹配回车键
  • \t匹配制表符
  • \v匹配垂直制表符
  • \f匹配换页符
  • \0匹配null字符
  • \xhh匹配\u00\uFF
  • \uhhhh匹配\u0000\uFFFF

# 3.5 字符类[]

字符类表示一些可供选择的字符,只要匹配一个就可以,把所有待匹配的字符放入方括号类,组成一个字符类

var reg = /[abc]/;
var str = 'a';
reg.test(str); // true

在字符类中下面两种字符有个特殊含义

脱字符^

  • 表示除开方括号字符的任意字符都可以匹配,[^abc]表示匹配除开 a, b, c 之外的任意字符
  • [^]表示匹配一切字符,范围比点字符.要大
  • 脱字符只有在字符类的第一位才有效,否则就是字面量字符

连字符-

  • /[0-9]/表示[0123456789]
  • /[a-z]/表示 26 个小写字母
  • /[A-Z]/表示 26 个大写字母

# 3.6 预定义模式

常见匹配模式的简写

  • \d等同于[0-9]
  • \D等同于[^0-9]
  • \w等同于[a-zA-Z0-9_]
  • \W等同于[^a-zA-Z0-9_]
  • \s等同于[\r\n\t\v\f]
  • \S等同于[^\r\n\t\v\f]
  • \b匹配词的边界
  • \B匹配非词边界,即在词的内部

# 3.7 重复类

/a{2,9}/匹配 a 字符重复 2 次到 9 次

var reg = /^1\d{10}$/; // 匹配 1 开头的总共十一位的数字

# 3.8 量字符

  • ?匹配 0 次或 1 次,等同于{0, 1}
  • *匹配 任意次,等同于{0,}
  • +匹配 1 次或多次,等同于{1,}

# 3.9 贪婪模式

量字符的原则是最大可能匹配,知道下一个字符不匹配为止,我们称这种匹配模式为贪婪模式

如果想讲贪婪模式改为非贪婪模式,则在量字符后面加上?

  • *?表示某个模式出现 0 次或多次,采用非贪婪模式
  • +?表示某个模式出现 1 次或者多次匹配,采用非贪婪模式
/\d+/.exec('453'); // ["453", index: 0, input: "453", groups: undefined]
/\d+?/.exec('453'); // ["4", index: 0, input: "453", groups: undefined]

# 3.10 修饰符

  • g:全局匹配,主要用于搜索和替换
  • i:忽略大小写进行匹配
  • m:多行匹配模式

# 3.11 分组匹配

正则表达式的括号表示分组匹配

var reg = /(\d)a(\D)/;
var str = '4ab6a4';
var result = str.match(reg);
result;
// ["4ab", "4", "b", index: 0, input: "4ab6a4", groups: undefined]

正则表达式内部可以使用\1,\2,来表示括号匹配的内容,\1表示获取第一个括号匹配的内容

/(.)a(\d)\1\2/.test('ba4b4'); // true

实例:html 标签闭合匹配

var tagReg = /<([^>]+)>[^>]*<\/\1>/;
var str = '<span>abc</span>';
tagReg.exec(str)
// (2) ["<span>abc</span>", "span", index: 0, input: "<span>abc</span>", groups: undefined]

# 3.11.1 非组捕获

(?:x)称为非组捕获,表示不返回匹配x的内容

var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"];

# 3.11.2 先行断言

x(?=y)称为先行断言,x只有在y前面才匹配,y不计入匹配结果

var m = 'xaxy'.match(/x(?=y)/);
m;
// ["x", index: 2, input: "xaxy", groups: undefined]

# 3.11.3 先行否定断言

x(?!y)称为先行否定断言,只有不在y前面的x才匹配,y不计入匹配结果

var m = 'abcacb'.match(/c(?!a)/);
m;
// ["c", index: 4, input: "abcacb", groups: undefined]

# 4. 常用的正则表达式

下面是一些常用的正则表达式,仅供参考,方便日常开发使用

  • /^([1][3,4,5,6,7,8,9])\d{9}$/:手机号码
  • /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/:邮件地址
  • /^[a-zA-Z]\w{5,17}$/:密码(以字母开头,长度在 6~18 之间,只能包含字母、数字和下划线)
  • /^((\d{18})|([0-9x]{18})|([0-9X]{18}))$/:18 位身份证号码(数字,字母X结尾)
  • /^[a-zA-z]+://[^\s]*$/:网址(URL)
Last Updated: 9/20/2024, 7:36:32 AM