深入浅出正则表达式

74 阅读3分钟

什么是正则表达式?

是一种文本模式, 使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串

  • 声明方式
  1. 构造函数创建正则对象
/** 当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \) */
const reg = new RegExp('\\d+.*', 'g');
console.log(reg.test('hahah'));    // false
console.log(reg.test('12hhh'));    // true
console.log(reg.toString());       // /\d+.*/g
  1. 字符串直接量
const reg2 = /\d+.*/g;
console.log(reg2.test('hahah'));   // false
console.log(reg2.test('12hahah')); // true
console.log(reg2.toString());      // /\d+.*/g
  • 构成

一个有效的正则表达式

  1. 可以是一个单独的字符, 比如/jimous/g,用于完全匹配字符串'jimous'
const jimousReg = /jimous/g;
console.log(jimousReg.test('jimous is cool'));  // true
console.log(jimousReg.test('jimou'));           // false
  1. /[字符串+元字符]/修饰符的组合模式
const jimousReg2 = /jimous.*cool$/g; // 以'cool'收尾
console.log(jimousReg2.test('jimous is cool'));      // true
console.log(jimousReg2.test('jimous is cool ohhh')); // false

认识元字符

元字符作为正则表达式的特殊字符,具有很多特定的含义和用法,元字符决定这你的正则表达式的功能逻辑,巧妙利用元字符组合,可以写出非常优雅的正则匹配语句。这里以常用的一些元字符作为介绍,带大家了解正则表达式的元字符的作用。

  • 精确匹配
\d: 匹配数字字符
\D: 匹配非数字字符
\r: 匹配回车符
\s: 匹配任何空白字符
\S: 匹配任何非空白字符
\w: 匹配字母、数字、下划线
\W: 匹配非字母、数字、下划线
  • 匹配命中次数
*: 匹配前面的子表达式零次或多次
+: 匹配前面的子表达式一次或多次
?:  匹配前面的子表达式零次或一次
{n}: n为非负整数,表示匹配确定的n次
{n,}: 表示至少匹配n次
{n, m}: 最少匹配 n 次且最多匹配 m 次(m 和 n 均为非负整数,其中n <= m)
.: 圆点.  匹配除换行符之外的任何单个字符
  • 位置匹配
^: 匹配输入字符串的开始位置;
$: 匹配输入字符串的结束位置
  • 范围匹配
|: 或,eg: x|y, 匹配x或y
[]: 字符集合,匹配所包含的任意一个字符
[^]: 匹配未包含的任意字符

修饰符

  • g: global, 全局匹配,查找所有的匹配项
  • i: ignore,将匹配设置为不区分大小写
  • m: multi line,多行匹配,而不是整个字符串的开头和结尾,使边界字符 ^ 和 $ 匹配每一行的开头和结尾.
  • s: 特殊字符圆点 . 中包含换行符 \n (默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符)

运算符优先级

从高到低分别是:

  1. 转义符: \
  2. 圆括号和方括号: (), (?:), (?=), []
  3. 定位点和序列(即:位置和顺序): ^, $, \任何元字符、任何字符
  4. 替换运算符: |

字符具有高于替换运算符的优先级,所以对于元字符语法 'c|fool'用于匹配c或fool, 如果想要匹配cool或fool, 对应的语法规则应该是 '(c|f)ool'

RegExp对象

  • 属性

global: 判断是否设置了 "g" 修饰符; ignoreCase: 判断是否设置了 "i" 修饰符; lastIndex: 用于规定下次匹配的起始位置; multiline: 判断是否设置了 "m" 修饰符; source: 返回正则表达式的匹配模式

const reg = new RegExp('\\d+.*', 'i');
console.log(reg.global);      // false
console.log(reg.ignoreCase);  // true
console.log(reg.lastIndex);   // 0
console.log(reg.multiline);   // false
console.log(reg.source);      // \d+.*
  • 方法

eg:const regTest = new RegExp('cool', 'g');

  1. exec: 用于检索字符串中的正则表达式的匹配, 返回一个数组,对应匹配的结果。如果未找到匹配,则返回null;
const regText = 'jimous is cool, yes, very cool';

console.log(regTest.exec(regText));  // [ 'cool', index: 10, input: 'jimous is cool, yes, very cool', groups: undefined ]
console.log(regTest.exec(regText));  // [ 'cool', index: 26, input: 'jimous is cool, yes, very cool', groups: undefined ]
  1. test: 用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false
console.log(regTest.test('jimous is cool'));  // true
console.log(regTest.test('jimous is happy')); // false
  1. toString: 返回正则表达式的字符串值

console.log(regTest.toString()); // /cool/g

  1. compile: 用于改变和重新编译正则表达式
regTest.compile('happy', 'g');
console.log(regTest.toString());              // /happy/g
console.log(regTest.test('jimous is happy')); // true

字符串的正则交互api

eg: const regText = 'jimous is cool~'

  • search: 检索与正则表达式相匹配的值
const regTest = /jimous/g;

console.log(regText.search(regTest)); // 0
console.log('hahah'.search(regTest)); // -1
  • match: 找到一个或多个正则表达式的匹配
const regTest = /o/g;
console.log(regText.match(regTest));  // ['o', 'o', 'o']
console.log('hahah'.match(regTest));  // null
  • replace: 替换与正则表达式匹配的子串,并返回替换后新的字符串
const regTest = /cool/g;
const newStr = regText.replace(regTest, 'happy');
console.log(newStr);  // jimous is happy~
  • split: 把字符串分割为字符串数组
const regTest = /cool/g;
console.log(regText.split(regTest));  // [ 'jimous is ', '~' ], 等同于 regText.split('cool')

小结

从看不懂正则,到了解规则后看懂别人的正则,再到自己手写正则,大量的练习会让你对正则的书写更加得心应手,熟能生巧。

俗话说举一反三,了解正则表达式的构成,字符+元字符的排列组合,构成的正则语法,再加上优先级运算规则,从一些简单的正则表达式入手去学习,再慢慢自己写一些常用的正则,渐渐的你会对正则的写法越来越熟悉。正则的学习过程,加深了我对有穷自动机下对字符匹配的执行过程,让我对它的运行原理有了更加验证式的理解和认识,也许在工作生活中可能依然完全用不上这些理解,不过对于自己的认知水平,也是一种向上的提升。