RegExp笔记

57 阅读3分钟

RegExp

NFA, none deterministic finite automaton: 非确定有限状态自动机 : .* DFA, deterministic finite automaton:确定有限状态自动机):

  1. 优先选择最左的匹配结果
  2. 替代优先判断 如 .*"[^"]替代 如 ((?!.)*?),

字符组

\w : [0-9a-zA-Z_] ; \W : [^0-9a-zA-Z_]

\s : 表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页 符,即[^\t\v\n\r\f]

. : 表示从除换行符、回车符、行分隔符(\u2028)和段分隔符(\u2029)以外的字符,即[^\n\r\u2028\u2029]

表示任意字符:[\d\D], [\w\W], [\s\S]

\n : 第 n 个子捕获匹配的子字符串(【捕获的数目以左括号计数】)

非贪婪匹配

{m,n}?; {m,}? ; ??

【特殊】 /good|nice/分支匹配也是从左往右顺序进行深度搜索进行匹配(所有的正则都是最左匹配)

位置匹配

^, $, (?=p) : /Jack(?=Sprat)/会匹配到'Jack'仅当它后面跟着'Sprat'。/Jack(?=Sprat|Frost)/匹配的'Sprat'和'Frost'都不是匹配结果的一部分。 (?<=p) :/(?<=Jack)Sprat/会匹配到' Sprat '仅仅当它前面是' Jack ' 。 (?!p) : x(?!y) (?<!p) :(?<!y)x

\b :匹配一个词的边界

  1. /\bm/匹配“moon”中的‘m’;
  2. /oo\b/并不匹配"moon"中的'oo',因为'oo'被一个“字”字符'n'紧跟着。
  3. /oon\b/匹配"moon"中的'oon',因为'oon'是这个字符串的结束部分。这样他没有被一个“字”字符紧跟着。
  4. /\w\b\w/将不能匹配任何字符串,因为在一个单词中间的字符永远也不可能同时满足没有“字”字符跟随和有“字”字符跟随两种情况;同理/(a(?=c)b)/,不可能匹配 a 后面是 c,但为 b 的字符串;/.^/

\B :匹配一个非单词边界 => (?!\b)

tips
  1. []减少回溯 :"[^"]*
  2. 位置字符和序列字符优先级比 | 高:/^abc|bcd$/ => /(^abc)|(bcd$)/
  3. 需转义字符:^$.*+?|\\/[]{}=!:-,

String.replace(reg, function(full, key, value){})

Regex 构造函数生成正则的转义字符需要添加: new RegExp('\\d') => /\d/

image-20210723204352602转存失败,建议直接上传图片文件

/asd(\d+)qwe(\d+)/.test("as!asd1231qwe432!dsw");
RegExp.$1; // 1231
RegExp.$2; // 432
RegExp.lastMatch; // asd1231qwe432
RegExp.lastParen; // 432  // 捕获为最后一次()
RegExp.leftContext; // as!
RegExp.rightContext; // !dsw
特殊理解:
// if-then-else匹配
(?(?=condition)(then1|then2|then3)|(else1|else2|else3))
// 可以理解为
(?=condition)(then1|then2|then3) 和 (else1|else2|else3)

匹配示例:

// 后面是 (\d{3})+$ 的间隙
// 每 3 个数字添加逗号 ","
const result = "12345678".replace(/(?=(\d{3})+$)/g, ","); // 12,345,678

// 匹配不是开头的 a,b,c
const regex = /(?!^)[a-c]/, /^(?![a-c])/

// 解析一个完整的url
/^(?:([A-Za-z]+):)?(\/{0,2})([.a-zA-Z\/\d]+)(?::(/d{0, 4})+)\?([a-zA-Z\d]=[a-zA-Z\d])(#[a-zA-Z\d])?$/

计算字符串表达式

var calculate = function(expr) {
  expr = expr.replace(/ +/g, '')
  const operExp = /\(\d+[+\-*\/]\d+\)|\(-?\d+\)|\d+[*\/]\d+|-?\d+[+-]\d+(?![*\/\d])/
  while(operExp.test(expr)) {
      expr = expr.replace(operExp, val => Math.floor(eval(val)))
  }
  return expr
}

// console.log(calculate("3+5/2"))
// console.log(calculate("2-3+4"))
// console.log(calculate("14-13/2"))

匹配最内层标签:

// 外层()仅代表(.)*关联,并不捕获
let reg = /<B>((?!<B>|<\/B>).)*<\/B>/g;
let str = "<B>asdad<B>123123</B>asdasd</B>";
reg.exec(str); // ["<B>123123</B>", "3", index: 8, input: "<B>asdad<B>123123</B>asdasd</B>", groups: undefined]
str.match(reg); // ["<B>123123</B>"]

// 捕获需要再包含()
// 一般使用正向否定查找的方式为x(?!y),但因为*可重复定义该查找方式:x(?=y),x(?!y),(?<!y)x同理
// ((?!<B>|<\/B>).)* => ((?!<B>|<\/B>).)?((?!<B>|<\/B>).)+
let reg2 = /<B>(((?!<B>|<\/B>).)*)<\/B>/g;
reg2.exec(str); //  ["<B>123123</B>", "123123", "3", index: 8, input: "<B>asdad<B>123123</B>asdasd</B>", groups: undefined]

getElementsByClassName

// /(^|\s)classname(\s|$)/
function getElementsByClassName(className) {
  var elements = document.getElementsByTagName("*");
  var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
  var result = [];
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if (regex.test(element.className)) {
      result.push(element);
    }
  }
  return result;
}

exec 和 match 的区别

// 1. exec 为 RegExp 方法, match 是 String 方法
// 2. 当正则无子表达式,且非全局匹配时,两者返回相同;
//    当正则无子表达式,且定义为全局匹配时,match 返回全局匹配;
//    当正则有子表达式,且定义为非全局匹配时,exec 返回整个正则匹配和子表达式匹配,match 返回一次匹配的多个整正则匹配字符串;
//    当正则有子表达式,且定义为全局匹配,match 返回全局匹配的多个整正则匹配字符串;
//    总结:exec 返回与是否有子匹配相关;match 返回与全局,整个字符串匹配相关;
//    exec 可多次进行匹配,reg.lastIndex 保存最后一次匹配的索引

// 非全局有子匹配
/.{1}(12)(3)/.exec("asd 123"); // [" 123", "12", "3", index: 3, input: "asd 123", groups: undefined]
"asd 123".match(/.{1}(12)(3)/); // [" 123", "12", "3", index: 3, input: "asd 123", groups: undefined]

// 全局有子匹配
"asd 123a123".match(/.{1}(12)(3)/g); //  [" 123", "a123"]
const reg = /.{1}(12)(3)/g,
  str = "asd 123a123";
reg.exec(str); // [" 123", "12", "3", index: 3, input: "asd 123a123", groups: undefined] // 下次匹配从index: 3开始
reg.exec(str); //  ["a123", "12", "3", index: 7, input: "asd 123a123", groups: undefined]
reg.exec(str); // null : 重置index: 0