学如逆水行舟,不进则退
什么是正则表达式
Regular Expression使用单个字符串来描述、匹配一系列符合某种规则的字符串。
简单来说就是按照某种规则去匹配符合条件的字符串。
举个栗子,我们要查找当前目录的所有txt文件,就可以通过正则表达式来完成:
find ./ -name *.txt
当然这只是个很简单的例子。
其实真正用到的有可能是这个样子的:
^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$
这是验证邮箱的一个规则,所以想要在实际工程中运用,还需要深入学习学习。
而且有大神写出了一个正则表达式的可视化工具,可以方便的查看你的正则表达式的意思:
点击链接:Regexper
还有一款工具可以实时显示的也很不错:
点击链接:Regulex
通配符
下面我们开始学习一些通配符,看看他们都是什么意思。
\b WordBoundary,单词的边界;
\d Digit,数字;
. AnyChar,任意字符;
^ Start开头;
$ End结尾;
{4} 表示重复4次;
[/-] / 或者 - 其中一个,中括号表示或;
() 表示分组;
$1 表示提取前面括号里的分组内容,按顺序排列$1 $2 $3……
例如:
^\d{4}[/-]\d{2}[/-]\d{2}$
匹配的就是像2017/01/07或者2017-01-07这样的时间格式。
RegExp对象
JavaScript中通过内置对象RegExp来支持正则表达式。
而实例化RegExp对象有两种方法:
- 字面量
- 构造函数
第一种方法:
var reg=/\bis\b/g;
"He is a boy,this is a dog.".replace(reg,"IS")
//先声明了一个变量存储表达式,然后替换字符串里所有的is为IS
//表达式中的g表示global全局
第二种方法:
var reg = new RegExp("\\bis\\b","g");
"He is a boy,this is a dog.".replace(reg,"IS")
//在js中使用\需要转义,所以再加一个\;
修饰符
- g :global全文搜索,不加的话默认匹配第一个;
- i :ignore case 忽略大小写,默认大小写敏感;
- m :multiple lines多行搜索;
元字符
元字符是在正则表达式中有特殊含义的非字母字符。
* + ? $ ^ . | \ () [] {}
字符 | 含义 |
---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | 与X对应的控制符(ctrl+X) |
字符类
我们可以用[]来构建一个简单的类,所谓类就是符合某种规则的一类字符,而不是特指的单个字符;
例如:
"a1b2c3d4".replace(/[abc]/g,"x")
就会得到:"x1x2x3d4"
字符类取反
我们可以使用元字符^创建反向类/负向类;
反向类表示不属于某类的内容;
比如[^abc]表示不是a或b或c的内容;
例如:
"a1b2c3d4".replace(/[^abc]/g,"x")
结果是axbxcxxx
范围类
正则表达式还提供范围类;
我们可以使用[a-z]来表示从a到z的任意字符;
在[]组成的类内部还可以连写像这样[a-zA-Z0-9]
举个几栗子:
"a1b2c3d4xYz".replace(/[a-z]/g,"x")
结果是x1x2x3x4xYx
"a1b2c3d4XYZ".replace(/[a-zA-Z]/g,"x")
结果是x1x2x3x4xxx
"2017-01-07".replace(/[0-9]/g,"x")
结果是xxxx-xx-xx
"2017-01-07".replace(/[0-9-]/g,"x")
结果是xxxxxxxxxx
预定义类
正则表达式还提供一些预定义类来匹配常见的字符类
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符 |
\S | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符(字母、数字、下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
例如:匹配一个 “ab+数字+任意字符” 的字符串
只需要这样:ab\d.
就可以解决了。
当然还有边界字符:
字符 | 含义 |
---|---|
^ | 以×××开始 |
$ | 以×××结束 |
\b | 单词边界 |
\B | 非单词边界 |
量词
字符 | 含义 |
---|---|
? | 出现零次或一次(最多一次) |
+ | 出现一次或多次(最少一次) |
* | 出现零次或多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 最少出现n次 |
举个栗子:
\d{20}\w?\d\w+\d*\d{3}\w{3,5}\d{3,}
什么意思呢,来看图:
正则表达式的贪婪和非贪婪模式
贪婪模式顾名思义就是尽可能多的匹配,知道匹配失败为止。
例如:
"12345678".replace(/\d{3,6}/g,"x")
结果是:"x78"
非贪婪模式就是尽可能少的匹配,一旦匹配成功就不再进行匹配。
怎么使用非贪婪模式呢?很简单,在量词后面加上“?”就可以了。
例如:
"12345678".replace(/\d{3,6}?/g,"x")
结果是:"xx78"
分组
我们使用()可以到达分组的效果,使量词可以作用于整个分组而不是紧挨的单个字符。
例如:
"a1b2c3d4".replace(/[a-z]\d{3}/g,"x")
结果是:"xd4"
或
使用|
可以达到或的效果
反向引用
如果我们想把2017-01-07这样一个字符串替换为01/07/2017这样。
可以用$和()来实现
"2017-01-07".replace(/(\d{4})-(\d{2})-(\d{2})/g,"$2/$3/$1")
结果是:"01/07/2017"
分组默认是自动排序的,如果不想被分组呢,只需要在括号里面加上“?:”就可以忽略该分组了:
前瞻
正则表达式从文本的头部向尾部进行解析,文本的尾部方向,称为“前”。
前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言,后瞻方向相反。
需要注意的是Javascript并不支持后瞻。
符合和不符合特定断言分别称为正向/肯定匹配和负向/否定匹配。
名称 | 正则 |
---|---|
正向前瞻 | exp(?=assert) |
负向前瞻 | exp(?!assert) |
再来个栗子:
"a2*34v8".replace(/\w(?=\d)/g,"x")
结果:"x2*x4x8"
"a2*34v8".replace(/\w(?!\d)/g,"x")
结果:"ax*3xxx"