正则表达式学习

167 阅读1分钟

正则表达式

正则表达式可以用于 查找多项匹配,还可以查询字符串中符合指定匹配模式的字符串

  1. 模糊匹配 .

  2. 精准匹配 /a/

  3. 字符簇: [] 范围匹配 /[a-zA-Z0-9]/ 字符簇也只表示一个字符

  4. 否定字符集:^ 注意否定字符集要写在[]里面和匹配位置的不一样

    到目前为止,已经创建了一个想要匹配的字符集合,但也可以创建一个不想匹配的字符集合。 这些类型的字符集称为否定字符集( negated character sets)。

以上这都是匹配一个位置

  1. 匹配符 i忽略大小写 g来匹配全局
  2. reg.test返回布尔值 string.match(reg)返回匹配的字符
  3. 一次或多次:+
  4. 零次或多次:*
  5. 惰性匹配:? 写在 , +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的

正则表达式默认是贪婪匹配;

贪婪(greedy)匹配会匹配到符合正则表达式匹配模式的字符串的最长可能部分,并将其作为匹配项返回。 另一种方案称为懒惰(lazy)匹配,它会匹配到满足正则表达式的字符串的最小可能部分。

/t.*?i/

  1. 匹配位置:^开始位置和$结束位置 指定位置,相当于给结果针对位置进行筛选

  2. 元字符:

\w 等于[a-zA-Z0-9_]

\W 等于 小写w的取反

\d 数字

\D 非数字 "2001: A Space Odyssey".match(/\D/g).length;// 结果是17

\s搜寻空格 此匹配模式将匹配空格、回车符、制表符、换页符和换行符。 可以认为这类似于元字符 [ \r\t\f\n\v]

\S 非空白符

  1. 数量说明符 {n,m} {n,} {m}

  2. 模糊匹配 ?

    /colou?r/

  3. 正向先行断言和负向先行断言 一般使用test进行断言? 非获取

    正向先行断言会查看并确保搜索匹配模式中的元素存在。 正向先行断言的用法是 (?=...),其中 ... 就是需要存在但不会被匹配的部分。

    另一方面,负向先行断言会查看并确保搜索匹配模式中的元素不存在。 负向先行断言的用法是 (?!...),其中 ... 是希望不存在的匹配模式。 如果负向先行断言部分不存在,将返回匹配模式的其余部分。

    尽管先行断言有点儿令人困惑,但是这些示例会有所帮助。

    let quit = "qu";
    let noquit = "qt";
    let quRegex= /q(?=u)/;
    let qRegex = /q(?!u)/;
    quit.match(quRegex);//q
    noquit.match(qRegex);//q  如果想把qt都匹配的话可以使用/q[^u]/
    

    这两次 match 调用都将返回 ["q"]

    先行断言的更实际用途是检查一个字符串中的两个或更多匹配模式。 多条件的查询模式

  4. 检查混合字符组

    /P(engu|umpk)in/
    
  5. 表达式里使用捕获组重用模式 (\w+) \1 \1 一般结合test和match使用

    当你想要匹配一个像下面这样多次出现的单词

    用圆括号会有一个副作用,使相关的匹配会被缓存,会在match里打印出来,此时可用 ?: 放在第一个选项前来消除这种副作用。

    let repeatStr = "row row row your boat";
    

    你可以使用 /row row row/。但如果你不知道重复的特定单词,怎么办? 捕获组 可以用于找到重复的子字符串。

    捕获组是通过把要捕获的正则表达式放在括号中来构建的。 在这个例子里, 目标是捕获一个包含字母数字字符的词,所以捕获组是将 \w+ 放在括号中:/(\w+)/

    分组匹配的子字符串被保存到一个临时的“变量”, 可以使用同一正则表达式和反斜线及捕获组的编号来访问它(例如:\1)。 捕获组按其开头括号的位置自动编号(从左到右),从 1 开始。

    下面的示例是匹配被空格隔开的两个相同单词:

    let repeatRegex = /(\w+) \1 \1/;
    repeatRegex.test(repeatStr); // Returns true
    repeatStr.match(repeatRegex); // Returns ["row row row", "row"]
    

    在字符串上调用 .match() 方法将返回一个数组,其中包含它最终匹配到的子字符串及其捕获组。

  6. 使用捕获组搜索和替换 string.replace() $1

    使用美元符号($)访问替换字符串中的捕获组。

    "Code Camp".replace(/(\w+)\s(\w+)/, '$2 $1');//返回Camp Code
    //在这里的表达式里使用捕获组重用不会生效
    "Code Camp".replace(/(\w+)\s\1/, '$2 $1');//返回Code Camp
    

    运算符优先级

    字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"

image-20230802162722958.png

匹配位置

在ES5中,共有6个锚字符**^ $ \b** \B (?=p) (?!p)

共有四个:表达位置的这四者是个位置。

^(脱字符)匹配开头,在多行匹配中匹配行开头。

$(美元符号)匹配结尾,在多行匹配中匹配行结尾。

\b是单词边界,例如:"[JS] Lesson_01.mp4".replace(/\b/g, '#')// => "[#JS#] #Lesson_01#.#mp4#"

\B是非单词边界

(?=l)正向先行断言 :表示'l'字符前面的位置,例如:"hello".replace(/(?=l)/g, '#')// => "he#l#lo"*

(?!l) 负向向先行断言:表示后面不是'l'字符的位置,例如 "hello".replace(/(?!l)/g, '#')// => "#h#ell#o#"*

(?<=l)正向后行语言 表示'l'字符后面的位置,例如:'Hello, world!'.replace(/(?<=l)/g,'#')//=>'Hel#l#o, worl#d!'

'Hello, world!'.replace(/(?<=l)\w+/g,'#')//=>'Hel#, worl#!'

(?<!l)负向后行语言 表示前面不是'l'字符的位置,例如:'Hello, world!'.replace(/(?'#H#e#llo#,# #w#o#r#ld#!#'

'Hello, world!'.replace(/(?'#, #!'

"[JS] Lesson_01.mp4".replace(/(?<=\w)\b/g, '#');//=>'[JS#] Lesson_01#.mp4#'

举例正则表达式匹配中文:

"单行文本=获取难()".replace(/(?<=[\u4E00-\u9FFF])(?![\u4E00-\u9FFF])/g, '#');
//=>'单行文本#=获取难#()'

正则表达式匹配英文:

"departmentselectfield_0t78i3w6=departmentselectfield_eoowwfo4".replace(/(?<=\w)\b/g, '#');
//=>'departmentselectfield_0t78i3w6#=departmentselectfield_eoowwfo4#'

matchAll:

//const regexp = /(?=\w+)\b/g;
//单词边界会包括起始位置和结束位置 即0和length
// const regexp = /\b/g;
const regexp = /\w+/g;
//找到符号
// const regexp = /\W/g;
const str = "table=football()foosball";

const matches = str.matchAll(regexp);
console.log(matches)
for (const match of matches) {
  console.log(
    `找到 ${match[0]} 起始位置=${match.index} 结束位置=${
      match.index + match[0].length
    }.`)
      console.log(match)
}