最近遇到几个很类似的题目,都用到正则做字符串操作,就想总结一下。
知识点
正则创建方式
var reg = new RegExp(/are/, 'g');
var reg = /are/i;
注意使用构造函数时字符的转义规则。
Expression Flags
正则模式匹配符
\g
:在字符串中查找所有可能的匹配,返回结果是多个
\i
:匹配时不区分大小写
\m
:多行匹配
正则匹配查询:
str.search(reg)
返回值为str中第一个与reg匹配的位置,不匹配返回-1str.match(reg)
返回匹配数组,依赖全局标志greg.exec(str)
返回一个数组,数组里存储的是第一个匹配项的相关信息reg.test(str)
返回值Boolean
正则常用语法
特殊代码
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
重复
代码 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
反义
代码 | 说明 |
---|---|
\W | 匹配任意不是字母和数字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
对正则中各种括号的使用总结了一下:
()
是为了提取匹配的字符串。正则表达式中有几个()
就有几个相应的匹配字符串。[]
是定义匹配的字符范围。比如[a-zA-Z0-9]
表示要匹配英文字符和数字。{}
一般用来表示匹配的长度,比如\d{3}
表示匹配三个数字。
Greedy VS Lazy
正则的贪婪模式和非贪婪模式,Greedy就是尽可能多的去匹配,来看一个匹配html标签的例子:
|
|
你可能认为使用正则式/<.+>/
就可以匹配到<em>
和</em>
两个结果,然而事实是正则式会很贪婪的从第一个<
匹配到最后一个>
,也就是实际匹配到的是<em>Hello World</em>
。
可以通过Lazy的方式去尽可能少的匹配,正则式/<.+?>/
就可以匹配到你想要的,通过在+
后面添加?
就可以尽可能少的匹配,所以每当遇到>
就会停止匹配,测试一下"<em>Hello World</em>".match(/<.+?>/)
可以发现只匹配到一个,想要找到所有匹配就借助expression flags,global match的作用就是找到所有匹配项,而不是找到第一个匹配项之后就停下,正则式为/<.+?>/g
。
或者,其实Greedy同样可以实现相应的功能,方法就是让 <
和>
之间的字符不匹配>
,正则式为/<[^>]+>/
。
String.prototype.Replace
replace方法也是经常用到的,可能之前对这个方法的使用还仅仅停留在"hi world".replace(/hi/, "hello")
这样简单的替换使用上,replace真正的能力还没体验到,直接上🌰:
实现交换一个字符串中两个单词的位置
|
|
下面具体解释:replace第一个参数正则式/(\w+)\s(\w+)/
会匹配到的就是()
包裹的两个单词,第二个参数可以为函数或字符串。
1.函数必须有返回值,参数为:
$0
是这个正则式在原串中匹配到的子串,本例中则为Harry Potter
,其实换个字符串更好理解,比如"*&^Harry Potter^%&$%#"
被正则式匹配的子串为Harry Potter
。$n
是第n
个括号匹配到的字符串,本例中正则有两个括号,$1
匹配第一个括号,匹配到Harry
,$2
匹配第二个括号,匹配到Potter
。
2.替换字符串中可以插入特殊变量名,同样$n
表示插入第 n 个括号匹配的字符串。
有关正则的题目
题目一
前不久同学问了一个问题,将一个字符串中所有中文符号转为对应的英文符号。
|
|
题目二
按所给的时间格式输出指定的时间。
格式说明:
输入:
输出:
|
|
题目三
实现模版解析函数。
|
|
题目四
CSS中经常有类似background-image
这种通过-
连接的字符,通过JS设置样式的时候需要将这种样式转换成backgroundImage驼峰格式,请完成此转换功能
- 以
-
为分隔符,将第二个起的非空单词首字母转为大写 -webkit-border-image
转换后的结果为 webkitBorderImage
|
|
|
|
题目五
将 rgb 颜色字符串转换为十六进制的形式,如rgb(255, 255, 255)
转为 #ffffff
.
|
|
Regex Golf
Warmup
Anchors
可以发现需要match的字符串都以ick为结尾
It never ends
不允许通过$
匹配字符串结尾,可以用\b
来匹配单词的开头和结尾
Ranges
考察字母的范围以及字符串的边界
Backrefs
考察反向引用,可以发现,开头出现的三个字母之后还会出现,后向引用用于重复搜索前面某个分组匹配的文本。例如,\1
代表分组1匹配的文本。
Abba
可以发现要求不要match类似abba这样的字符串,先构造abba,还是用到后向引用(\w)(\w)\2\1
,不匹配就用到零宽断言(?!exp)
,匹配后面不是exp的串。然而(?!(\w)(\w)\2\1)
只匹配了左边的,右边的也匹配上了。。。不应该match的串是xxxabbaxxx
这样子的,那么应该就是^(?!.*(\w)(\w)\2\1)
。
持续更新…
Reference
一个挺实用的正则小工具RegExr