JS

前端必须掌握的正则知识

By John Han
Picture of the author
Published on
async 异步

前端必须掌握的正则知识

正则表达式(Regular Expression,简写为 regex、regexp)是前端绕不过去的坎。

学习正则时觉得好像挺简单,使用它时又觉得好难。

1. 什么是正则表达式

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

它可以用来操作字符串,如:

  • 检索字符串
  • 替换字符串

正则表达式可以用形式化语言理论的方式来表达

正则表达式由常量算子组成,它们分别表示字符串的集合和在这些集合上的运算

在 Perl 中就内建了一个功能强大的正则表达式引擎。

JavaScript 中也有正则表达式。

2. 正则表达式基本语法

一个正则表达式通常被称为一个模式用来描述或者匹配一系列匹配某个句法规则的字符串。

大部分正则表达式的形式都有如下的结构:

  • 选择
  • 数量限定
  • 匹配

2.1 选择

  • 竖线|,代表选择(或集),优先级较低。

    如:gray|grey 可以匹配 grey 或 gray.

2.2 数量限定

某个字符串后的数量限定符用来限定前面这个字符允许出现的个数

常见的数量限定符包括:+、?、*。

  • +: 至少出现一次(>= 1),必须得有
  • ?: 最多只可以出现一次(0 || 1),简记:有没有都行
  • *: 可以不出现,也可以出现一次或者多次(>= 0)

2.3 匹配

圆括号()可以用来定义操作符的范围和优先度。

如:

  • gr(a|e)y 等价于 gray|grey

    圆括号()定义了操作符“|”的范围。

  • (grand)?father 匹配 fathergrandfather

    圆括号()定义了操作符“?”的范围。

上述这些构造子都可以自由组合;

如:H(ae?|ä)ndel和H(a|ae|ä)ndel是相同的。

因为 ae?和a|ae是等价的。

3. PCRE 表达式

正则表达式有不同的写法,使用最广泛的是 PCRE。

PCRE 的全称是 Perl Compatible Regular Expression,即 Perl 兼容的正则表达式。

各种编程语言如 Java、Python、C#、JavaScript 实现的就是这种正则表达式。

PCRE 表达式(部分): |

总结


  • \ 代表特殊字符
  • 处理范围问题
  • [] 处理字符集合
  • () 包含独立的匹配模式块

4. 创建正则表达式

表达式字面量:

var re = /ab+c/;

使用 RegExp 对象的构造函数:

var re = new RegExp("ab+c");

5. 编写一个正则表达式的模式

  • 简单字符正则表达式模式, 如 /abc/

  • 简单和特殊字符的组合, 如/abc/ 或 /Chapter (\d+).\d/

5.1 标志

通过标志可以进行高级搜索。

  • g : 全局搜索

  • i : 不区分大小写搜索

  • m : 多行搜索

  • s : 允许 . 匹配换行符

  • u : 使用 unicode 码的模式进行匹配

  • y : 执行“粘性(sticky)”搜索

    var re = /\w+\s/g;
    var re = new RegExp("\\w+\\s", "g");
    

6. 使用正则表达式

正则表达式主要做两件事:

  • 查找
  • 测试

JavaScript 中,正则表达式可以被用于:

  • RegExp 的 exec 和 test 方法
  • String 的 match、replace、search 和 split 方法
序号字符描述返回值
1exec查找匹配的 RegExp 方法返回一个数组或 null
2test测试是否匹配的 RegExp 方法Boolean
3match查找匹配的 String 方法返回一个数组或 null
4replace查找匹配的 String 方法返回一个数组
5matchAll查找所有匹配的 String 方法一个迭代器(iterator)
6search测试匹配的 String 方法并且使用替换字符串替换掉匹配到的子字符串
7split分隔一个字符串,将分隔后的子字符串存储到数组中的 String 方法返回一个数组

应用示例

RegExp 的 exec 方法:

var myArray = /d(b+)d/g.exec("cdbbdbsbz");
console.log(myArray);
// ["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]

结果:exec 方法会返回匹配结果其他正则属性

String 的 match 方法:

var myArray = "cdbbdbsbzdbbbbbbbbdfkk".match(/d(b+)d/g);
console.log(myArray);
// ["dbbd", "dbbbbbbbbd"]

结果:exec 方法会返回匹配结果其他正则属性

7. 常见正则

反转字符串:

let re = /(\w+)\s(\w+)/;
let str = "John Smith";
// $1 和 $2 指明括号里先前的匹配
let newstr = str.replace(re, "$2, $1");
console.log(newstr);
// Smith, John

从 URL 中提取子域名:

var url = "http://xxx.domain.com";
console.log(/[^x]+/.exec(url)[0].substr(7));
// /[^.]+/ 的意思是:多个非"."的字符串集合,指匹配“.”之前的字符集合
// logs "xxx"

从 URL 中提取 params:

let url = "http://www.nowcoder.com?key=1&key=2&key=3&key=4&test=4#hehe";
function getUrlParam(sUrl, sKey) {
var result = {};
// “\??“ -> 匹配有0个或1个 "?"
// "(\w+)=(\w+)&?" -> 匹配以“=”相连且0或1个“&”结尾的任意多个字符
sUrl.replace(/\??(\w+)=(\w+)&?/g, function (a, k, v) {
  if (result[k] !== void 0) {
    var t = result[k];
    result[k] = [].concat(t, v);
  } else {
    result[k] = v;
  }
});
if (sKey === void 0) {
  return result;
} else {
  return result[sKey] || "";
}
}
console.log(getUrlParam(url, key));

判断手机号是否合法:

function isPhoneNum(num) {
if (typeof num === "number") return false;

// 以 1 开头,第二个字符为 [35789] 中任意一个,然后是 9 个数字结尾
let reg = /^1[35789]\d{9}$/g;

return reg.test(num);
}

参考

正则表达式 | Wikipedia

正则表达式 | MDN

RegExp(正则表达式) | MDN

Stay Tuned

Want to become a Next.js pro?
The best articles, links and news related to web development delivered once a week to your inbox.