正则表达式(个人笔记)

方法: RegExp - exec test
String - match matchAll replace search split

描述
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\d 匹配一个数字字符。等价于 [0-9]
\D 匹配一个非数字字符。等价于 [^0-9]
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]’。
\W 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,“o{1,3}” 将匹配 “fooooood” 中的前三个 o。‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。
{n,} n 是一个非负整数。至少匹配n 次。例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等价于 ‘o+’。‘o{0,}’ 则等价于 ‘o*’。
{n} n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘(’ 或 ‘)’。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (
(?=pattern) 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?<=pattern) 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows“能匹配”2000Windows“中的”Windows",但不能匹配"3.1Windows“中的”Windows"。
(?<!pattern) 反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows“能匹配”3.1Windows“中的”Windows",但不能匹配"2000Windows“中的”Windows"。

(1)

(?=xox) 和 (?<=xox) 的区别:

可以看作此两者是匹配字符之间的一个虚无的 “空位”。

(?=xox) 匹配 xox 之前的空位,而 (?<=xox) 匹配 xox 之后的空位。

所以对于 abxoxcd

(?=xox)..    匹配 xo

..(?=xox)    匹配 ab

(?<=xox)..    匹配 cd

..(?<=xox)    匹配 ox

(2)

?=?!?<= ?<! 用于限定它前后的表达式,不能单独使用,本身没有作用。

  • a(?=b) 匹配后面有 b 的 a。
  • a(?!b) 匹配后面没有 b 的 a。
  • (?<=a) b 匹配前面有 a 的 b。
  • (?<!a) b 匹配前面没有 a 的 b。

描述 ?=?!?<= ?<! 的 “Positive/Negative lookahead/lookbehind assest” 的现行翻译“正先行断言”“正向肯定预查”之类,都不易理解或者说不准确甚至错误。lookaround 指前后看而不是“预查”,意为作用于前后表达式,即 lookahead(指向前看而不是“先行”)和 lookbehind(指向后看而不是“后发”)的合称;assert 指判断而不是“断言”;Positive 和 Negative 指肯否定而不是正负。

贪婪

*、+限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。

例如,您可能搜索 HTML 文档,以查找括在 H1 标记内的章节标题。该文本在您的文档中如下:

<H1>Chapter 1 - 介绍正则表达式</H1>

**贪婪:**下面的表达式匹配从开始小于符号 (<) 到关闭 H1 标记的大于符号 (>) 之间的所有内容。

/<.*>/

**非贪婪:**如果您只需要匹配开始和结束 H1 标签,下面的非贪婪表达式只匹配

/<.*?>/

如果只想匹配开始的 H1 标签,表达式则是:

/<\w+?>/

通过在 *+? 限定符之后放置 ?,该表达式从"贪心"表达式转换为"非贪心"表达式或者最小匹配。

附:
反向引用还可以将通用资源指示符 (URI) 分解为其组件。假定您想将下面的 URI 分解为协议(ftp、http 等等)、域地址和页/路径:

var str = "http://www.runoob.com:80/html/html-tutorial.html";
var patt1 = /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
arr = str.match(patt1);
for (var i = 0; i < arr.length ; i++) {
    document.write(arr[i]);
    document.write("<br>");
}

----------------------------------- 华丽的分割线 -----------------------------------

捕获分组
https://wangdoc.com/javascript/stdlib/regexp.html
https://segmentfault.com/a/1190000020171825
https://blog.csdn.net/csm0912/article/details/81206848
https://blog.csdn.net/lihefei_coder/article/details/53022253

JavaScript正则表达式分组模式:捕获性分组与非捕获性分组及前瞻后顾(断言)

捕获性分组:()
捕获性分组工作模式()会把每个分组里匹配的值保存起来。

比如利用捕获性分组把 hello world 互换成 world hello:
方法一:通过exec函数


var str = 'hello world';            //首先创建好字符串
var pattern = /([a-z]+)\s([a-z]+)/; //先通过正则匹配这个字符串,用分组模式来获取这两个单词
var arr = pattern.exec(str); // exec方法返回的是一个数组,包含匹配到的字符串以及分组(也称子串)里的值

console.log(arr); //['hello world','hello','world']  
console.log(arr[0]); //'hello world' 匹配到的字符串
console.log(arr[1]); //'hello' 第一个分组([a-z]+)的值
console.log(arr[2]); //'world' 第二个分组([a-z]+)的值

//这时候两个分组的值都得到了,接下来用字符串拼接法实现互换
var n_str = arr[2]+' '+arr[1];
console.log(n_str) //world hello

方法二:通过属性$1-9

var str = 'hello world';            
var pattern = /([a-z]+)\s([a-z]+)/; 
pattern.test(str); //这个地方必须运行正则匹配一次,方式不限,可以是test()、exec()、以及String的正则方式

console.log(RegExp.$1) //'hello' 第一个分组([a-z]+)的值
console.log(RegExp.$2) //'world' 第二个分组([a-z]+)的值

var n_str = RegExp.$2+' '+RegExp.$1;
console.log(n_str) //world hello

方法三:通过String的replace()

var str = 'hello world'; 
var pattern = /([a-z]+)\s([a-z]+)/; 
var n_str = str.replace(pattern,"$2 $1"); //这里的$1、$2与方法二里的RegExp.$1、RegExp.$2作用是相同的。
console.log(n_str) //world hello

非捕获性分组:(??
非捕获性分组工作模式下分组(?:)会作为匹配校验,并出现在匹配结果字符里面,但不作为子匹配返回。

比如利用非捕获性分组获取字符串000aaa111,而且只返回一个值为aaa111的数组:


//先看用捕获性分组匹配会返回什么
var str1 = '000aaa111';             
var pattern = /([a-z]+)(\d+)/; //捕获性分组匹配
var arr = pattern.exec(str1);  
console.log(arr) //['aaa111','aaa','111']   结果子串也获取到了,这并不是我们想要的结果


//非捕获性分组
var str2 = '000aaa111';
var pattern2 = /(?:[a-z]+)(?:\d+)/; //非捕获性分组匹配
var arr2 = pattern2.exec(str2);  
console.log(arr2) //['aaa111']  结果正确    

前瞻:(?=)和(?!)
前瞻分为正向前瞻和反(负)向前瞻,正向前瞻(?=表达式)表示后面要有什么,反向前瞻(?!=表达式)表示后面不能有什么。

前瞻分组会作为匹配校验,但不出现在匹配结果字符里面,而且不作为子匹配返回。

正向前瞻匹配一批图片格式:

//正向前瞻,匹配.jpg后缀文件名
var str = '123.jpg,456.gif,abc.jpg';
var partern = /\w+(?=\.jpg)/g; //正向前瞻匹配
console.log(str.match(partern)); //['123', 'abc']   返回结果正确,没有匹配456.gif

反向前瞻匹配一批字母加数字:

//反向前瞻,匹配3个及以上的a,而且后面不能有000的字符
var str = 'aaa000 aaaa111 aaaaaaa222';
var partern = /a{3,}(?!000)/g; //反向前瞻匹配
console.log(str.match(partern)); //['aaaa', 'aaaaaaa']   返回结果正确,没有匹配aaa000

后顾:(?<=)和(?<!) —JavaScript不支持
后顾分为正向后顾和反(负)向后顾,正向后顾(?<=表达式)表示前面要有什么,反向后顾(?<!表达式)表示前面不能有什么。

//正向后顾
(?<=abc) //前面需要有abc

//反向后顾
(?<!abc) //前面不能有abc

名词解释:

前瞻 = 先行断言
(?=) 正向前瞻 = 正向零宽先行断言
(?!) 反向前瞻 = 负向前瞻 = 负向零宽先行断言

后顾 = 后发断言
(?<=) 正向后顾 = 正向零宽后发断言
(?<!) 反向后顾 = 负向后顾 = 负向零宽后发断言

版权声明:本文为CSDN博主「lihefei_coder」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lihefei_coder/article/details/53022253

发布了25 篇原创文章 · 获赞 5 · 访问量 1136

猜你喜欢

转载自blog.csdn.net/tinfengyee/article/details/102551273