文章目录
JavaScript之正则表达式小记
一篇记录了正则表达式基础的笔记。
通过有道云笔记阅读体验感觉更干净些,就是加载比较慢~
转义字符
在 HTMl 中转义字符以 &
符号开头,分号;
结尾。比如小于号(<
)就可以写 <
或者 <
,空格可以写成
;
在JavaScript 中转义字符一般以反斜杠""开头,比如回车(\r
)、换行(\n
)、水平制表符(\t
)、垂直制表符(\v
)、换页符(\f
)。反斜杠则以两个\
表示(即\\
)。
// 转义双引号
var str = "abcde\"fg";
// 换行符
var str2 = "abcd\nefg";
// 回车换行符
var str3 = "abcd\r\nefg";
// 水平制表符,相当于键盘上的 Tab 键 (\b 想当于键盘上的退格键)
var str4 = "abcd\tefg";
两种创建正则的方法
有两种创建正则表达式的方式,一种是直接量(字面量)语法,一种是通过内置的对象 RegExp。
直接量语法
/pattern/attributes
比如匹配字符串 abc
:
var reg = /abc/, str = "abcde";
console.log(reg.test(str));
// true
检查字符串 str
中是否存在 abc
。
通过内置对象 RegExp
语法
new RegExp(pattern, attributes);
同样是匹配字符串 abc
:
var reg = new RegExp("abc"), str = "abcde";
console.log(reg.test(str));
// true
参数 pattern 的值可以是已有的正则表达式,但是如果在创建的时候不加关键字 new
,返回的将是已有正则表达式的引用,而不是新创建的 RegExp 对象。
通过下面的两个例子理解上一句话
-
使用
new
创建正则表达式:var reg = new RegExp("abc"), str = "abcde"; var newReg = new RegExp(reg); newReg.myAttr = "123"; console.log(newReg.myAttr); // "123" console.log(reg.myAttr); // undefined
-
不使用
new
创建正则表达式:var reg = new RegExp("abc"), str = "abcde"; var newReg = RegExp(reg); newReg.myAttr = "123"; console.log(newReg.myAttr); // "123" console.log(reg.myAttr); // "123"
参数
参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。
简单的说 pattern 就是我们写的规则,而 attributes 是规则的修饰符。
修饰符 g
,即 global,是否执行全局匹配。
var reg = new RegExp("abc","g"), str = "abcdefgabc";
console.log(str.match(reg));
// ["abc", "abc"]
// 查看正则表达式是否全局匹配
console.log(reg.global);
// true
使用全局匹配修饰符,匹配到两个 "abc"
。可以通过 reg.global
去判断当前的正则表达式是否为全局匹配。
修饰符 i
,即 ignoreCase,是否忽略大小写。
var reg = new RegExp("abc","i"), str = "ABCDEFG";
console.log(str.match(reg));
// ["ABC", index: 0, input: "ABCDEFG", groups: undefined]
// 查看正则表达式是否忽略大小写
console.log(reg.ignoreCase);
// true
使用忽略大小写修饰符,匹配到 "abc"
。可以通过 reg.ignoreCase
去判断当前的正则表达式是否忽略大小写。
修饰符 m
,即 multiline,是否以多行模式执行模式匹配。
var reg = new RegExp("abc","gm"), str = "abcdefghjk\nabcde";
console.log(str.match(reg));
// ["abc","abc"]
// 查看正则表达式是否以多行模式执行模式匹配
console.log(reg.multiline);
// true
使用多行匹配修饰符,匹配到两个 "abc"
。可以通过 reg.multiline
去判断当前的正则表达式是否以多行模式执行模式匹配。
注意:所有的字符串如果不手动添加转义字符 \n
都为一行。
表达式(方括号)
在正则表达式中,一对方括号代表一位字符串的匹配范围。
例如,匹配字符串中三位连续的数字:
var reg = /[1234567890][1234567890][1234567890]/g, str = "12345asda7890";
console.log(str.match(reg));
// ["123", "789"]
匹配到符合的字符串片段后,就从当前位置继续向后匹配,不会回头再去匹配。
匹配所有的数字可简写为 [0-9]
,即 ASCII 码中数字 0 到 9 范围内的所有内容。
匹配所有的字母可简写 [A-z]
,所有的大写字母可简写 [A-Z]
,所有的小写字母可简写 [a-z]
。
非 ^
符号 ^
在正则表达式不同的位置拥有不同的含义:
/^abc/
- 在正则表达式的头部表示匹配以abc
开头的字符串(符号$
匹配字符串的结束)。/[^abc]/
- 放在正则表达式的表达式中则表示匹配除了abc
以外的所有字符(非)。
放在正则表达式头部:
var reg = /^abc/g, str = "abcdefg", str2 = "123abcdefg";
console.log(str.match(reg));
// ["abc"]
console.log(str2.match(reg));
// null
第二行的头部也是可以匹配到的:
var reg = /^abc/gm, str = "123abcdefg\nabcs";
console.log(str.match(reg));
// ["abc"]
符号 ^
放在表达式中意思为 非:
var reg = /[^abc]/g, str = "abcdefg";
console.log(str.match(reg));
// ["d", "e", "f", "g"]
或 |
在正则表达式中,符号 |
为 或 的意思
符号 |
可用于子表达式 ()
中:
var reg = /(123|456|789)[A-z]/g, str = "123bb45ccc";
console.log(str.match(reg));
// ["123b"]
也可用于表达式(方括号) []
中:
var reg = /[123|456|789][A-z]/g, str = "1aa4Ab5Cc6E";
console.log(str.match(reg));
// ["1a", "4A", "5C", "6E"]
甚至就写在正则中。例如,检查一个字符串的首尾是否存在数字:
var reg = /^\d|\d$/g, str = "1ab";
console.log(reg.test(str));
// true
元字符
在正则表达式中,元字符(Metacharacter)是拥有特殊含义的字符。
- 元字符
.
,用于查找单个字符,除了换行和行结束符。
var str = "That's hot!", patt1 = /h.t/g;
console.log(str.match(patt1));
// "hat", "hot"
- 元字符
\w
,用于查找单词字符(world),相当于[0-9A-z_]
。
var str = "Give 100%!", patt1 = /\w/g;
console.log(str.match(patt1));
// ["G", "i", "v", "e", "1", "0", "0"]
元字符 \W
,用于查找非单词字符,相当于 [^\w]
。
- 元字符
\d
,用于查找数字,即[0-9]
。
var str = "Give 100%!", patt1 = /\d/g;
console.log(str.match(patt1));
// [ "1", "0", "0"]
元字符 \D
,用于查找非数字字符,相当于 [^\D]
。
- 元字符
\s
,用于查找空白字符,即[\r\n\t\v\f ]
。
空白字符可以是:
- 空格符
(space character)
- 制表符
\t
(tab character) - 回车符
\r
(carriage return character) - 换行符
\n
(new line character) - 垂直换行符
\v
(vertical tab character) - 换页符
\f
(form feed character)
var str = "Is this all\nthere is?", patt1 = /\s/g;
console.log(str.match(patt1));
// [" ", " ", "↵", " "]
元字符 \S
,用于查找非空白字符,相当于 [^\s]
。
- 元字符
\b
,用于匹配单词边界。
var str = "Is this all\nthere is?", patt1 = /\bt/g;
console.log(str.match(patt1));
// ["t", "t"]
元字符 \B
,用于查找非单词边界,相当于 [^\b]
。
var str = "Is this all\nthere is?", patt1 = /(\bthis\b|\bt\B)/g;
console.log(str.match(patt1));
// ["this", "t"]
\xxx
元字符用于查找以八进制数xxx
规定的字符。
对字符串中的八进制 127 (W) 进行全局搜索:
var str = "Hello World or word!", patt1 = /\127/g;
console.log(str.match(patt1));
// ["W"]
忽略大小写呢?
var str = "Hello World or word!", patt1 = /\127/gi;
console.log(str.match(patt1));
// ["W", "W"]
\xdd
元字符查找以十六进制数dd
规定的字符。
对字符串中的十六进制 57 (W) 进行全局搜索:
var str = "Hello World or word!", patt1 = /\x57/g;
console.log(str.match(patt1));
// ["W"]
\uxxxx
元字符用于查找以十六进制数xxxx
规定的 Unicode 字符。
对字符串中的十六进制 0057 (W) 进行全局搜索:
var str = "Hello World or word!", patt1 = /\u0057/g;
console.log(str.match(patt1));
// ["W"]
因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
"\u54c8\u55bd" // 哈喽
量词
变量 n
可以代表任何字符。
量词 n+
,表示变量 n
至少出现 1 次。
var str = "Hello World or word!", patt1 = /o+/g;
console.log(str.match(patt1));
// ["o", "o", "o", "o"]
量词 n*
,表示变量 n
可以出现 0 次到无数次。
var str = "or oo", patt1 = /o*/g;
console.log(str.match(patt1));
// ["o", "", "", "oo", ""] "oo" -> 贪婪匹配
量词 n?
,表示变量 n
可以出现 0 次或 1 次。
var str = "or oo", patt1 = /o?/g;
console.log(str.match(patt1));
// ["o", "", "", "o", "o", ""]
量词 n{X}
,表示变量 n
可以出现 X 次。
var str = "or oo ooo", patt1 = /o{2}/g;
console.log(str.match(patt1));
// ["oo", "oo"]
量词 n{X,Y}
,表示变量 n
可以出现 X 次到 Y 次。
var str = "or oo ooo", patt1 = /o{2,3}/g;
console.log(str.match(patt1));
// ["oo", "ooo"]
量词 n{X,}
,表示变量 n
至少出现 X 次。
var str = "or oo ooo", patt1 = /o{1,}/g;
console.log(str.match(patt1));
// ["o", "oo", "ooo"]
量词 ^n
,匹配任何开头为 n 的字符串。
var str = "abc def", str2 = "db cefc", patt1 = /^d/g;
console.log(str.match(patt1));
// null
console.log(str2.match(patt1));
// ["d"]
字符串 "abc def"
以 a
开头
量词 n$
,匹配任何结尾为 n 的字符串。
var str = "abc def", str2 = "ab defc", patt1 = /c$/g;
console.log(str.match(patt1));
// null
console.log(str2.match(patt1));
// ["c"]
量次 ^
和 $
同时出现,字符串只能是中间的内容
var str = "abcdabcd", str2 = "abcd", patt1 = /^abcd$/g;
console.log(str.match(patt1));
// null
console.log(str2.match(patt1));
// ["abcd"]
量词 ?=n
,匹配匹配任何其后紧接指定字符串 n 的字符串。
对其后紧跟 “all” 的 “is” 进行全局搜索:
var str="Is this all there is";
var patt1=/is(?= all)/g;
console.log(str.match(patt1));
// ["is"]
量词 ?=n
,也有称为正向预查(正向断言)。
量词 ?!n
,匹配任何其后没有紧接指定字符串 n 的字符串。
对其后没有紧跟 “all” 的 “is” 进行全局搜索:
var str="Is this all there is";
var patt1=/is(?! all)/gi;
console.log(str.match(patt1));
// ["Is", "is"]
量词 ?!n
,也有称为非正向预查(非正向断言)。
贪婪匹配与非贪婪匹配
上一节所说的 量词 默认使用的是贪婪匹配,它会尽可能多的去匹配符合规则的字符串。
var str = "aaaaaaaaa", reg = /a+/g;
console.log(str.match(reg));
// ["aaaaaaaaa"]
贪婪匹配转换为非贪婪匹配,在量词后加上符号 ?
即可。
var str = "aaaaaaaaa", reg = /a+?/g;
console.log(str.match(reg));
// ["a", "a", "a", "a", "a", "a", "a", "a", "a"]
var str = "11222333", reg = /\d{2,3}?/g;
console.log(str.match(reg));
// ["11", "22", "23", "33"]
var str = "11222333", reg = /\d??/g;
console.log(str.match(reg));
// ["", "", "", "", "", "", "", "", ""]
量词 n?
,表示匹配出现 0 次或者 1 次,再加上一个符号 ?
转换为非贪婪匹配,那么匹配的就是 0 次。
子表达式 ()
括号 ()
中的内容称为子表达式
\1
匹配第一个子表达式中匹配的内容
// 匹配第一个子表达式中匹配的内容(反向引用第一个子表达式匹配的内容)
var reg = /(\w)\1/g;
var str = "aaaa";
var reg = /(\w)\1\1\1/g;
console.log(str.match(reg));
// ["aaaa"]
\2
匹配第二个子表达式中匹配的内容,有几个子表达式就可以写到几。
var str = "aaaa", str2 = "aabb";
var reg = /(\w)\1(\w)\2/g;
console.log(str.match(reg));
// ["aaaa"]
console.log(str2.match(reg));
// ["aabb"]
RegExp 对象属性
global 属性用于判断某个正则表达式是否具有修饰符 g
。
ignoreCase 属性用于判断某个正则表达式是否具有修饰符 i
。
multiline 属性用于判断某个正则表达式是否具有修饰符 m
。
lastIndex 属性标示下一次匹配的字符位置。常与 exec()
方法一起出现。
source 属性用于返回模式匹配所用的文本。
一个例子加深理解:
var str = "www.abc.com\n123.ab.cn";
var reg = /\w\./gm;
console.log(reg.lastIndex); // 0
console.log(str.match(reg)); // ["w.", "c.", "3.", "b."]
console.log(reg.global); // true
console.log(reg.ignoreCase); // false
console.log(reg.multiline); // true
console.log(reg.source); // "\w\."
reg.lastIndex = 4;
console.log(reg.lastIndex); // 4
console.log(str.match(reg)); // ["w.", "c.", "3.", "b."]
reg.lastIndex = 4;
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["c.", index: 6, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 8
console.log(reg.exec(str)); // ["3.", index: 14, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 16
console.log(reg.exec(str)); // ["b.", index: 17, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 19
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0
exec()
当匹配到符合规则的字符时便会停下,等待下一次调用,直到字符串匹配结束。
RegExp 对象方法
test()
方法
test()
方法用于检测一个字符串是否匹配某个模式.
语法
RegExpObject.test(string)
如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
比如,检索 “www”
var str = "www.abc.com";
var patt1 = /www/;
console.log(patt1.test(str));
// true
exec()
方法
exec()
方法用于检索字符串中的正则表达式的匹配。
语法
RegExpObject.exec(string)
如果 exec()
找到了匹配的文本,则返回一个结果数组。否则,返回 null。
在上一次匹配的基础上接着匹配。
var reg = /ab/g;
var str = "abababab";
console.log(reg.lastIndex); // 0 -> 当前开始匹配的索引位置
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 2
console.log(reg.exec(str)); // ["ab", index: 2, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["ab", index: 4, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 6
console.log(reg.exec(str)); // ["ab", index: 6, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 8
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
exec()
当匹配到符合规则的字符时便会停下,等待下一次调用,直到字符串匹配结束。
reg.lastIndex
是可读写的。
var reg = /ab/g;
var str = "abababab";
console.log(reg.lastIndex); // 0 -> 当前开始匹配的索引位置
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
reg.lastIndex = 0;
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
注意:如果不加修饰符 g
,永远从索引 0 开始匹配。
exec()
方法与子表达式 ()
还是上面那个例子,但是使用 exec()
方法去匹配
var str = "aaaa", str2 = "aabb";
var reg = /(\w)\1(\w)\2/g;
console.log(reg.exec(str2));
// ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]
此类数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。
index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。
compile()
方法
compile()
方法用于在脚本执行过程中编译正则表达式。
compile()
方法也可用于改变和重新编译正则表达式。
该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。
语法
RegExpObject.compile(regexp,modifier)
-
参数 regexp 为正则表达式。
-
参数 modifier 为修饰符。
不推荐compile方法。你可以使用 RegExp 构造函数来得到相同效果。
字符串上使用正则表达式
字符串的 match()
方法
同样的例子使用 match()
方法:
var str = "aabb";
var reg = /(\w)\1(\w)\2/g;
console.log(str.match(reg));
// ["aabb"]
如果不加全局修饰符 g
呢:
var str = "aabb";
var reg = /(\w)\1(\w)\2/;
console.log(str.match(reg));
// ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]
加了全局修饰符后结果与使用 exec()
方法类似。
字符串的 search()
方法
search()
方法返回匹配到字符串的位置。
var str = "123aabb";
var reg = /(\w)\1(\w)\2/;
console.log(str.search(reg));
// 3
如果匹配不到则返回 -1
:
var str = "123abcd";
var reg = /(\w)\1(\w)\2/;
console.log(str.search(reg));
// -1
字符串的 split()
方法
split()
方法以特定的规则去拆分字符串:
var str = "ab0c2de2f4gh5d";
var reg = /\d/g;
console.log(str.split(reg));
// ["ab", "c", "de", "f", "gh", "d"]
以数字为界限去拆分字符串
字符串的 replace()
方法
replace()
方法以特定的规则去替换字符串:
var str = "what is you name?";
console.log(str.replace("a","b"));
// "whbt is you name?"
把第一个 "a"
替换为 "b"
。
注意,replace()
方法第一个参数不是正则表达式时,无法访问全局。
使用正则表达式:
var reg = /a/g;
var str = "what is you name?";
console.log(str.replace(reg,"b"));
// "whbt is you nbme?"
把所有的 "a"
替换为 "b"
。
replace()
方法可引用子表达式匹配到的值,例如,如何把形如 XXYY 的字符串变成 YYXX。
var reg = /(\w)\1(\w)\2/g;
var str = "aabb 123 1122";
console.log(str.replace(reg,"$2$2$1$1"));
// "bbaa 123 2211"
在 replace()
方法的第二个参数可以通过 $1
去引用第一个子表达式匹配到的值。 同理 $2
为第二个。
把某个字符替换为 $:
// 在 `replace()` 方法中,符号 `$` 有转义的意思,若想把某个字符替换为 `$`,最好写为 `$$`:
var reg = /(\w)\1/g;
var str = "aabb 123 1122";
console.log(str.replace(reg,"$")); // "$$ 123 $$"
console.log(str.replace(reg,"$$")); // "$$ 123 $$"
console.log(str.replace(reg,"$1")); // "ab 123 12"
replace()
方法可传入回掉函数:
var reg = /(\w)\1(\w)\2/g;
var str = "aabb 123 1122";
console.log(str.replace(reg, function(val, $1, $2){
// val 为全局结果 $1 为第一个子表达式匹配到的值 $2 ...
return $2 + $2 + $1 + $1
})); // "bbaa 123 2211"
练习,the-first-name 转为 theFirstName
var reg = /-(\w)/g;
var str = "the-first-name";
console.log(str.replace(reg, function(val, $1){
return $1.toUpperCase()
})); // "theFirstName"