Note

正则表达式

2022年07月05日 Tuesday · 6 min read
必备技能

常用语法

  • **.** - 除换行符以外的所有字符。
  • **^** - 字符串开头。
  • **$** - 字符串结尾。
  • \d,\w,\s - 匹配数字、字符、空格。
  • \D,\W,\S - 匹配非数字、非字符、非空格。
  • **[abc]** - 匹配 a、b 或 c 中的一个字母。
  • **[a-z]** - 匹配 a 到 z 中的一个字母。
  • **[^abc]** - 匹配除了 a、b 或 c 中的其他字母。
  • **aa|bb** - 匹配 aa 或 bb。
  • **?** - 0 次或 1 次匹配。
  • ***** - 匹配 0 次或多次。
  • **+** - 匹配 1 次或多次。
  • **{\*n\*}** - 匹配 n次。
  • **{\*n\*,}** - 匹配 n次以上。
  • **{\*m\*,\*n\*}** - 最少 m 次,最多 n 次匹配。
  • (*expr*) - 捕获 expr 子模式,以 \1 使用它。
  • (?:*expr*) - 忽略捕获的子模式。
  • (?=*expr*) - 正向预查模式 expr
  • (?!*expr*) - 负向预查模式 expr

创建正则

字面量创建

使用//包裹的字面量创建方式是推荐的作法,但它不能在其中使用变量

let hd = "houdunren.com";
console.log(/u/.test(hd));//true

下面尝试使用 a 变量时将不可以查询

let hd = "houdunren.com";
let a = "u";
console.log(/a/.test(hd)); //false

虽然可以使用 eval 转换为js语法来实现将变量解析到正则中,但是比较麻烦,所以有变量时建议使用下面的对象创建方式

let hd = "houdunren.com";
let a = "u";
console.log(eval(`/${a}/`).test(hd)); //true

对象创建

当正则需要动态创建时使用对象方式

let hd = "houdunren.com";
let web = "houdunren";
let reg = new RegExp(web);
console.log(reg.test(hd)); //true

根据用户输入高亮显示内容,支持用户输入正则表达式

<body>
  <div id="content">houdunren.com</div>
</body>
<script>
  const content = prompt("请输入要搜索的内容,支持正则表达式");
  const reg = new RegExp(content, "g");
  let body = document
    .querySelector("#content")
    .innerHTML.replace(reg, str => {
      return `<span style="color:red">${str}</span>`;
    });
  document.body.innerHTML = body;
</script>

通过对象创建正则提取标签

<body>
  <h1>houdunren.com</h1>
  <h1>hdcms.com</h1>
</body>

<script>
function element(tag) {
  const html = document.body.innerHTML;
  let reg = new RegExp("<(" + tag + ")>.+</\\1>", "g");
  return html.match(reg);
}
console.table(element("h1"));

选择符

| 这个符号带表选择修释符,也就是 | 左右两侧有一个匹配到就可以。

检测电话是否是上海或北京的坐机

let tel = "010-12345678";
//错误结果:只匹配 | 左右两边任一结果
console.log(tel.match(/010|020\-\d{7,8}/)); 

//正确结果:所以需要放在原子组中使用
console.log(tel.match(/(010|020)\-\d{7,8}/));

匹配字符是否包含houdunrenhdcms

const hd = "houdunren";
console.log(/houdunren|hdcms/.test(hd)); //true

字符转义

转义用于改变字符的含义,用来对某个字符有多种语义时的处理。

假如有这样的场景,如果我们想通过正则查找/符号,但是 /在正则中有特殊的意义。如果写成///这会造成解析错误,所以要使用转义语法 /\//来匹配。

const url = "https://www.houdunren.com";
console.log(/https:\/\//.test(url)); //true

使用 RegExp 构建正则时在转义上会有些区别,下面是对象与字面量定义正则时区别

let price = 12.23;
//含义1: . 除换行外任何字符 	含义2: .普通点
//含义1: d 字母d   					含义2: \d 数字 0~9
console.log(/\d+\.\d+/.test(price));

//字符串中 \d 与 d 是一样的,所以在 new RegExp 时\d 即为 d
console.log("\d" == "d");

//使用对象定义正则时,可以先把字符串打印一样,结果是字面量一样的定义就对了
console.log("\\d+\\.\\d+");
let reg = new RegExp("\\d+\\.\\d+");
console.log(reg.test(price));

下面是网址检测中转义符使用

let url = "https://www.houdunren.com";
console.log(/https?:\/\/\w+\.\w+\.\w+/.test(url));

字符边界

使用字符边界符用于控制匹配内容的开始与结束约定。

边界符 说明
^ 匹配字符串的开始
$ 匹配字符串的结束,忽略换行符

匹配内容必须以www开始

const hd = "www.houdunren.com";
console.log(/^www/.test(hd)); //true

匹配内容必须以.com结束

const hd = "www.houdunren.com";
console.log(/\.com$/.test(hd)); //true

检测用户名长度为3~6位,且只能为字母。如果不使用 ^与$ 限制将得不到正确结果

<body>
  <input type="text" name="username" />
</body>

<script>
  document
    .querySelector(`[name="username"]`)
    .addEventListener("keyup", function() {
      let res = this.value.match(/^[a-z]{3,6}$/i);
      console.log(res);
      console.log(res ? "正确" : "失败");
    });
</script>

元子字符

元字符是正则表达式中的最小元素,只代表单一(一个)字符

字符列表

元字符 说明 示例
\d 匹配任意一个数字 [0-9]
\D 与除了数字以外的任何一个字符匹配 [^0-9]
\w 与任意一个英文字母,数字或下划线匹配 [a-zA-Z_]
\W 除了字母,数字或下划线外与任何字符匹配 [^a-zA-Z_]
\s 任意一个空白字符匹配,如空格,制表符\t,换行符\n [\n\f\r\t\v]
\S 除了空白符外任意一个字符匹配 [^\n\f\r\t\v]
. 匹配除换行符外的任意字符