一个例子
使用正则将一个数字以科学计数法进行表示,如:
// 10000000 => 10,000,000
现在用一个正则来解决
const str = '10000000'const reg = /(?=(\B)(\d{3})+$)/gstr.replace(reg, ',') // 10,000,000
修饰符
正则表达式是由模式
和修饰符
(可有可无)组成
常用的修饰符有:i
、g
、m
、u
、y
i
:匹配时不区分大小写
str = 'JavaScript'reg = /javascript/ireg.test(str) // => true
g
:匹配时会查找所有的匹配项,而不只是第一个
str = 'absKsdblsb'reg = /s/gstr.match(reg) // => [s, s, s]
m
:匹配多行(会影响^、$操作符)
str = 'ab\nab'reg = /^ab/mgstr.match(reg) // => [ab,ab]
u
:开启完整的 unicode 支持
y
:粘滞模式
str = 'Hello, world!';reg = /\w+/y;reg.lastIndex = 5; // 在位置 5 精确查找regexp.exec(str) // => null
字符类
字符类
是个特殊的字符,用来匹配字符集中字符
如:匹配字符串中的数字
| const str = 'jhsd123fg903d' |
|
|
| |
| str.match(/\d/g) |
常用的字符表达式见下表:
表达式 | 描述 | 含义 |
---|
. | 匹配单个字符,除了换行和行结束符 | (小数点)默认匹配除换行符之外的任何单个字符。例如,/.n/ 将会匹配 "nay, an apple is on the tree" 中的 'an' 和 'on',但是不会匹配 'nay'。如果 s ("dotAll") 标志位被设为 true,它也会匹配换行符。 |
\w | 匹配单词字符 | 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。例如, /\w/ 匹配 "apple," 中的 'a',"$5.28,"中的 '5' 和 "3D." 中的 '3'。 |
\W | 匹配非单词字符 | 匹配一个非单字字符。等价于 [^A-Za-z0-9_]。例如, /\W/ 或者 /[^A-Za-z0-9_]/ 匹配 "50%." 中的 '%'。 |
\d | 匹配数字 | 匹配一个数字。等价于[0-9]。例如, /\d/ 或者 /[0-9]/ 匹配"B2 is the suite number."中的'2'。 |
\D | 匹配非数字字符 | 匹配一个非数字字符。等价于[^0-9]。例如, /\D/ 或者 /[^0-9]/ 匹配"B2 is the suite number."中的'B' 。 |
\s | 匹配空白字符 | 匹配一个空白字符,包括空格、制表符、换页符和换行符。等价于[ \f\n\r\t\v\u00a0\u1680\u180e\u2000-u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。例如, /\s\w*/ 匹配"foo bar."中的' bar'。经测试,\s不匹配"\u180e",在当前版本Chrome(v80.0.3987.122)和Firefox(76.0.1)控制台输入/\s/.test("\u180e")均返回false。 |
\S | 匹配非空白字符 | 匹配一个非空白字符。等价于 [^ \f\n\r\t\v\u00a0\u1680\u180e\u2000-u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。例如,/\S\w*/ 匹配"foo bar."中的'foo'。 |
\b | 匹配单词边界 | 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。(不要和[\b]混淆了)使用"moon"举例:/\bm/匹配“moon”中的‘m’;/oo\b/并不匹配"moon"中的'oo',因为'oo'被一个“字”字符'n'紧跟着。/oon\b/匹配"moon"中的'oon',因为'oon'是这个字符串的结束部分。这样他没有被一个“字”字符紧跟着。/\w\b\w/将不能匹配任何字符串,因为在一个单词中间的字符永远也不可能同时满足没有“字”字符跟随和有“字”字符跟随两种情况。 |
\B | 匹配非单词边界 | 匹配一个非单词边界。匹配如下几种情况: (1)字符串第一个字符为非“字”字符 (2)字符串最后一个字符为非“字”字符 (3)两个单词字符之间 (4)两个非单词字符之间 (5)空字符串 |
\n | 匹配换行符 | 匹配一个换行符 (U+000A)。 |
...等等其他
例子
.
字符
| var str = 'aa1bb' |
| str.match(/(\w)\1.(\w)\2/g) |
|
|
| str = 'nay, an apple is on the tree' |
| str.match(/.n/g) |
\w
字符
var str = 'a1ds23;.?]'str.match(/\w/g) // => ['a', '1', 'd', 's', '2', '3']
\d
字符
var str = 'a1ds23;.?]'str.match(/\w/g) // => ['1', '2', '3']
\s
字符
var str = 'a1 ds2 3;.?]'str.match(/\w/g) // => [' ', ' '],共有两处
\b
字符
var str = '2split1;word3'str.match(/\b\d/g) // => [2],先匹配数字[2,1,3],而后单词边界的是 [2]
\B
字符
var str = '2split1;word3'str.match(/\B\d/g) // => [1, 3],先匹配数字[2,1,3],而后非单词边界的是 [1,3]
复用
复用即量词,常见的量词包括:*
、+
、?
、{n}
,量词可以在匹配多个相同的模式的时候很管用,避免了重复写相同的模式
一个小例子:
| str = 'ab1c2d345e' |
| str.match(/\d/ig) |
|
|
| |
| str.match(/\d+/ig) |
来看下面的解释
*
:匹配前面的模式0个或多个,相当于{0, n}
// 还是上面的例子// 使用 *str.match(/\d*/ig) // => ['', '', '1', '', '2', '', '345', '', '']// 这里因为 * 0个也会匹配,所以每个位置都会匹配到空字符
+
:匹配前面的模式1个或多个,相当于{1, n}
// 使用 +,同理,至少得一个才能匹配上str.match(/\d+/ig) // => ['1', '2', '345']
?
:匹配前面模式0个或1个,相当于{0, 1}
str = 'Should I write color or colour'// 这里 ? 表示前面的 u 有或者没有都行str.match(/colou?r/ig) // => [color, colour]
{n}
:表示一个范围,可以是{0,n},{n,} 或者{n,m}
,表示知道得有左位数和最多位数
str = 'erabuiababidjabababkjlsdababababkl'// 至少得有2个ab,最多匹配3个abstr.match(/(ab){2,3}/ig) // => [abab, ababab, ababab]
选择、组合、捕获、引用
选择
选择是由|
标识进行匹配,可以理解为or,如:a|b
表示匹配a或者b
str = 'absdfg'// 匹配s或者dstr.match(/s|d/ig) // => ['s', 'd']
组合(字符集合范围)
组合在常用的匹配模式中还是常用的,[]
用来组合匹配的范围或者其他
几个重要概念:
[^..]
表示非组合的内容,^
在开头代表不是后面要匹配的内容
[\b]
匹配一个退格,不要和 \b
混淆了
| |
| reg1 = /^[A-z]\d*/ig |
| reg1.test('s12314') |
|
|
| |
| reg2 = /^[A-z|\d]\d*/ig |
| reg2.test('s12314') |
| reg2.test('112314') |
| reg3 = /^[A-z|0-2]\d*/ig |
| reg3.test('312314') |
|
|
| |
| reg4 = /^[^A-z]\d*/ig |
| reg4.test('s12314') |
| reg4.test(';12314') |
捕获
捕获在匹配表达式中经常看到,他的作用非常强大,使用()
一对括号进行修饰,这样就可以捕获到匹配到里面的内容,捕获经常和引用
或者修饰符
(*、+...)结合使用
在讲用法前,需要补充一下排除捕获
,排除捕获也很重要很常用,可以用一些需要()
但又不需要捕获后的值,用?:
排除捕获
常见用法:
使用捕获获取具体内容 RegExp
的静态属性 $
| str = 'I like Java coding' |
|
|
| |
| reg = /\w*(JAVA)\w*/ig |
|
|
| |
| reg.test(str) |
| |
| console.log(RegExp.$1) |
| console.log(RegExp.$2) |
|
|
| |
| str.replace(reg, 'PHP') |
| str.replace(reg, '【$1】') |
| str.replace(reg, '$1Script') |
| str.replace(reg, ($, $1) => { |
| console.log('匹配到了' + $1) |
| return `【${$1}】` |
| }) |
| |
| str.replace(reg, '<span style="color:red">$1</span>') |
匹配表达式结合引用
使用
引用其实和前面讲到的RegExp
的静态属性类似,只不过引用是在匹配表达式中使用,写法不一样。在匹配表达式中使用 \1
\2
...斜杠加一个数字的形式引用所有引用的第一个,类似 $1、$2...
引用的顺序与()
的使用顺序相关联,规则:由左到右,由外到内,遇到排除捕获跳过当前()
str = 'qaabbccddq'reg = /(\w)\1/igstr.match(reg) // => ['aa', 'bb', 'cc', 'dd']
| str = 'qaaaabbbb11q' |
| reg = /(\w\w)\1(\d)\2?/ig |
| str.match(reg) |
|
|
| |
| reg1 = /(\w\w)\1((\d)\3)?/ig |
| str.match(reg1) |
|
|
| |
| reg2 = /(\w\w)\1(?:(\d)\2)?/ig |
| str.match(reg1) |
引用
引用在匹配表达式中使用 \1
这种以 斜杠和数字
结合的方式使用,需要注意的是,引用的数字和使用 ()
的规则相关,规则为:由左到右,由外到内,遇到排除捕获跳过当前()
,这一点很重要
关于引用的用法,详见前面 捕获
小结的使用方法即可
断言
通常我们要匹配的内容后面要跟着指定的内容,常见的断言x(?=y)
、x(?!y)
、(?<=y)x
、(?<!y)x
前瞻断言
前瞻断言主要是x(?=y)
和x(?!y)
,x(?=y)
表示匹配后面紧跟着y的x,x(?!y)
表示匹配后面不是y的x
| str = '1 candy costs 50€' |
|
|
| |
| str.match(/\d+(?=€)/) |
|
|
| |
| str.match(/\d+(?!€)/) |
后瞻断言
后瞻断言主要是(?<=y)x
和(?<!y)x
,(?<=y)x
表示匹配前面紧跟着y的x,(?<!y)x
表示匹配前面不是y的x
| str = '1 candy costs $50' |
|
|
| |
| str.match(/(?<=\$)\d+/) |
|
|
| |
| str.match(/(?<!\$)\d+/) |
贪婪与惰性
正则的量词通常都是遵循贪婪
原则,也就是有量词的时候,尽量匹配多的。而惰性则和这种原则相反,尽量匹配少,不匹配多。
惰性
使用?
紧跟在量词的后面,如:
`\d+?` // 匹配一个数字就行`\w{1,}?` // 匹配1个字母就行`\d*?` // 匹配0个数字 => ['', ...]
例子
| |
| str = 'I like "apples" a little more than "oranges"' |
|
|
|
|
| |
| |
| |
| |
| |
| str.match(/".+"/g) |
|
|
| |
| str.match(/".+?"/g) |
|
|
| |
| str.match(/"[^"]+"/g) |
RegExp属性、方法
属性
常见的属性:source,global,ignoreCase,multiline,lastIndex等等...
source
表示正则对象的原表达式内容以字符串的形式输出,不包含修饰符
| reg = /(\d\s)\1/ig |
|
|
| reg.source |
global
表示是否匹配全部内容,而不是匹配到第一个就停止匹配,返回Boolean类型
| reg = /(\d\s)\1/ig |
|
|
| reg.global |
ignoreCase
表示匹配是否忽略大小写,返回Boolean类型
| reg = /(\d\s)\1/ig |
|
|
| reg.ignoreCase |
multiline
表示多行匹配,有回车符,换下一行从头匹配
| reg = /(\d\s)\1/ig |
|
|
| reg.multiline |
lastIndex
在全局匹配时,表示当前匹配的的索引,初始为0,当匹配到结果时,lastIndex值变为最新匹配的位置,如果不能匹配到结果了,然后重0开始
| str = 'day by day' |
|
|
| reg = /\w+/g |
|
|
| reg.exec(str) |
| reg.lastIndex |
|
|
| reg.exec(str) |
| reg.lastIndex |
|
|
| reg.exec(str) |
| reg.lastIndex |
|
|
| reg.exec(str) |
| reg.lastIndex |
方法
常见的方法:exec、test
exec
一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null)
同上lastIndex
例子
test
一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。
str = '1a1aklk2b2bp'reg = /(\d\w)\1+/reg.test(str) // => true
String常见的正则方法
常用的方法:replace
、match
、matchAll
、search
、split
replace:字符串替换指定的内容(表达式匹配)
| str = 'I like Java coding' |
|
|
| str.replace(/JAVA/i, 'PHP') |
| str.replace(/(JAVA)/i, '<$1>') |
| str.replace(reg, ($, $1) => { |
| console.log('匹配到了' + $1) |
| return `【${$1}】` |
| }) |
match:匹配所有符合表达式的内容,返回数组,否则null
| str = 'd1sd2asf43d5' |
|
|
| str.match(/\d+/) |
| str.match(/\d+/g) |
| str.match(/\d\b/) |
| str.match(/\d\B/) |
| str.match(/\d\s/) |
matchAll:返回匹配正则表达式的迭代器,参数为 RegExp
类型,且必须带上 修饰符 g
,否则报错;其匹配结果返回一个 RegExpStringIterator
类型的迭代器
| str = 'd1sd2asf43d5' |
|
|
| iterator = str.matchAll(/\d+/g) |
| Object.prototype.toString.call(iterator) |
|
|
| |
| iterator.next() |
| iterator.next() |
| iterator.next() |
| iterator.next() |
| iterator.next() |

search:匹配正则表达式,如果匹配成功返回第一个匹配的位置,否则返回-1
| str = '1 apple costs $50' |
|
|
| str.search(/(?<=\$)\d+/) |
| str.search(/\d+/) |
| str.search(/\d[A-z]/) |
split:将以正则匹配的内容进行分割
| str = 'skJavaslkdJAVAllksdfJaVAlp' |
|
|
| |
| str.split(/javas?/i) |