logo头像

-------------

正则表达式开发指南

本文于 1706 天之前发表,文中内容可能已经过时。

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。

语法

字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\”匹配“\”而“(”则匹配“(”。
^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
+匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
.匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

使用技巧

. 和 [.]

. 特殊字符在中括号表达式时 如 [.] 只会匹配 .字符,等价于 .,而非匹配除换行符 \n 外的所有字符。

^ 和 [^指定字符串] 之间的区别

^ 指的是匹配字符串开始的位置
[^指定字符串] 指的是除指定字符串以外的其他字符串

(^[0-9])+     // 匹配有一至多个数字的字符串组合
[^[0-9]]+  // 匹配有一至多个不含数字的字符串组合

exec() 方法

定义和用法

exec() 方法用于检索字符串中的正则表达式的匹配。

语法

// string: 必需。要检索的字符串。
RegExpObject.exec(string);

返回值

返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

说明

exec() 方法的功能非常强大,它是一个通用的方法,而且使用起来也比 test() 方法以及支持正则表达式的 String 对象的方法更为复杂。

如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。此数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。除了数组元素和 length 属性之外,exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。我们可以看得出,在调用非全局的 RegExp 对象的 exec() 方法时,返回的数组与调用方法 String.match() 返回的数组是相同的。

但是,当 RegExpObject 是一个全局正则表达式时,exec() 的行为就稍微复杂一些。它会在 RegExpObject 的 lastIndex 属性指定的字符处开始检索字符串 string。当 exec() 找到了与表达式相匹配的文本时,在匹配后,它将把 RegExpObject 的 lastIndex 属性设置为匹配文本的最后一个字符的下一个位置。这就是说,您可以通过反复调用 exec() 方法来遍历字符串中的所有匹配文本。当 exec() 再也找不到匹配的文本时,它将返回 null,并把 lastIndex 属性重置为 0。

提示和注释

重要事项:如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串,就必须手动地把 lastIndex 属性重置为 0。

提示:请注意,无论 RegExpObject 是否是全局模式,exec() 都会把完整的细节添加到它返回的数组中。这就是 exec() 与 String.match() 的不同之处,后者在全局模式下返回的信息要少得多。因此我们可以这么说,在循环中反复地调用 exec() 方法是唯一一种获得全局模式的完整模式匹配信息的方法。

()和$1…$9的理解和使用

()就是起到一个分组作用,将匹配到的放到mathches集合中,$相当于集合名字,1-9就相当于索引,$1…$9相当于对应索引的值。

示例一

// 将yyyy-MM-dd格式的日期转换为yyyy年MM月dd日
const str = "2018-07-02";
const reg =/(\d{4})\-(\d{2})\-(\d{2})/;
const date = str.replace(reg,"$1年$2月$3日");
console.log(date); // "2018年07月02日"

示例二

// 将yyyy-MM-dd格式的日期转换为yyyy/MM/dd/
const str = "2018-07-02";
const reg =/(\d{4})\-(\d{2})\-(\d{2})/;
const date = str.replace(reg,"$1/$2/$3");
console.log(date); // "2018/07/02"

^在[]里面和在[]外面如何区分

^在[]里面

/[^0-9]/.test('abc') // true
/[^0-9]/.test('123') // false

归纳:^在[]里面代表是非数字,所以它代表是非。

^在[]外面

/^[0-9]/.test('abc') // false
/^[0-9]/.test('1bc') // true

归纳:^在[]外面代表是为首的数字,所以它代表头。

^在[]里面和在[]外面有一个记忆的方法:乌龟把头(^)缩进里面,变为无(非)头乌龟,乌龟把头(^)伸出来,变为头(首)领。

[\s\S]*?

非贪婪匹配任意字符串(包括换行符),将这个表达式放在()内,()的前后是定位用的、固定不变的字段。()是用来在「Get Group from Matched Text」中仅输出匹配的变动字段。

\s 空白符
\S 非空白符
[\s\S]任意字符
[\s\S]* 0个到任意多个字符
[\s\S]*? 0个到任意多个字符(非贪婪模式,即最短匹配情况)

gm

m表明可以进行多行匹配,g表明可以进行全局匹配,综合到一起就是可以进行多行全局匹配

评论系统未开启,无法评论!