正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。
正则表通常被用来检索、替换那些符合某个模式(规则)的文本。
例如验证表单:
其他语言也会使用正则表达式,作为前端萌新,这里我主要是利用JavaScript 正则表达式完成验证。
在 JavaScript 中,可以通过两种方式创建一个正则表达式。
方式一:通过调用RegExp对象的构造函数创建
var regexp = new RegExp(/Syoyu/); console.log(regexp); // /Syoyu/
方式二:利用字面量创建
var rg = /Syoyu/;
test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
var rg = /Syoyu/; console.log(rg.test(Syoyu));// 匹配字符中是否出现Syoyu 出现结果为true console.log(rg.test('Syoyu'));// 匹配字符中是否出现Syoyu 未出现结果为false
一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等。
特殊字符非常多,可以参考:
MDN
jQuery 手册:正则表达式部分
正则测试工具
修饰符 | 说明 |
---|---|
i | 不区分大小写搜索 |
g | 全局搜索 |
m | 多行搜索 |
s | 允许 . 匹配换行符 |
u | 使用unicode码的模式进行匹配 |
y | 执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始 |
var reg = /pattern/flags // 使用方法
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
边界符 | 说明 |
---|---|
^ | 表示匹配行首的文本(以谁开始) |
$ | 表示匹配行尾的文本(以谁结束) |
如果 ^和 $ 在一起,表示必须是精确匹配。
var rg = /Syoyu/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型 // /Syoyu/ 只要包含有Syoyu这个字符串返回的都是true console.log(rg.test('Syoyu')) // true console.log(rg.test('Syoyu1')) // true console.log(rg.test('Syoyu2')) // true var reg = /^Syoyu/; // 要求以Syoyu开头 console.log(reg.test('Syoyu')); // true console.log(reg.test('Syoyu')); // true console.log(reg.test('SSyoyu')); // false var reg1 = /^Syoyu$/; // 精确匹配 要求必须是 Syoyu console.log(reg1.test('Syoyu')); // true console.log(reg1.test('Syoyuu')); // false console.log(reg1.test('SSyoyuu')); // false console.log(reg1.test('SyoyuSyoyu')); // false
字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。
表示有一系列字符可供选择,只要匹配其中一个就可以了
var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true console.log(rg.test('andy'));//true console.log(rg.test('baby'));//true console.log(rg.test('color'));//true console.log(rg.test('red'));//false var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true console.log(rg1.test('aa'));//false console.log(rg1.test('a'));//true console.log(rg1.test('b'));//true console.log(rg1.test('c'));//true console.log(rg1.test('abc'));//true var reg = /^[a-z]$/ //26个英文字母任何一个字母返回 true - 表示的是a 到z 的范围 console.log(reg.test('a'));//true console.log(reg.test('z'));//true console.log(reg.test('A'));//false //字符组合 var reg1 = /^[a-zA-Z0-9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true //取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。 var reg2 = /^[^a-zA-Z0-9]$/; console.log(reg2.test('a'));//false console.log(reg2.test('B'));//false console.log(reg2.test(8));//false console.log(reg2.test('!'));//true
量词符用来设定某个模式出现的次数。
量词 | 说明 |
---|---|
* | 重复0次或更多次 |
+ | 重复1次或更多次 |
? | 重复0次或1次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
/^[a-zA-Z0-9_-]{6,16}$/ // 用户名只能为英文字母,数字,下划线或者短横线组成, 并且用户名长度为6~16位.
大括号 量词符. 里面表示重复次数
中括号 字符集合。匹配方括号中的任意字符.
小括号表示优先级
正则表达式在线测试
预定义类指的是某些常见模式的简写方式.
预定义类 | 说明 | |
---|---|---|
\d | 匹配0-9的任一数字相当于[0-9] | |
\D | 和\d相反, 匹配所有0-9以外的任一字符,相当于[^0-9] | |
\w | 匹配任意的字母、数字和下划线,相当于[a-zA-Z0-9_] | |
\W | 和\w相反,相当于[^a-zA-Z0-9_] | |
\s | 匹配空格,相当于[\t\r\n\v\f] | |
\S | 和\s相反,相当于[^\t\r\n\v\f] | |
. | 查找单个字符,除了换行和行结束符 | |
\b | 匹配单词边界。 | |
\B | 匹配非单词边界。 | |
查找 NULL 字符。 | \n | |
查找换行符 | \f | |
查找换页符 | \r | |
查找回车符 | \t | |
查找制表符 | \v | |
查找垂直制表符 |
案例:验证座机号码
说明 | exec |
---|---|
对字符串进行查找匹配,返回一个数组(未匹配到返回null) | test |
对字符串进行测试匹配,返回true或false | replace |
替换与正则表达式匹配的子串,返回替换后的值,原始值不变 | replaceAll |
match | 替换与正则表达式匹配的所有子串,返回替换后的值,原始值不变。 注意: 当regexp是字符串时,匹配所有字串 当regexp是正则表达式时,必须加上g修饰符,否则会报错 |
找到一个或多个正则表达式的匹配, 它返回一个数组,在未匹配到时会返回 null | matchAll |
search | 找到所有正则表达式的匹配, 它返回一个迭代器 注意:和replaceAll类似 |
检索与正则表达式相匹配的值,返回首次检索到的值的下标 | split |
把字符串分割为字符串数组 |
let str = 'Syoyu' let regexp = /y/ regexp.exec(str) // ['y', index: 1, input: 'Syoyu', groups: undefined]
regexp.exec(str)方法返回匹配项
注意:
如果没有修饰符g,返回的就是匹配的第一项
如果有g修饰符,返回第一个匹配项,并将紧随其后的位置保存在regexp.lastIndex中。下一次调用会从regexp.lastIndex位置匹配,返回下一个匹配项…
let str = 'my name is Syoyu' let regexp = /y/g let result = null while(result = regexp.exec(str)) { console.log(result.index) // 1 // 12 // 14 }
let str = 'my name is Syoyu' let regexp = /Syoyu/ let regexp1 = /syoyu/ regexp.test(str) // true regexp1.test(str) // false
查找匹配项,然后返回 true/false 表示是否存在
let str = 'my name is Syoyu' let regexp = /y/ let regexp1 = /y/g str.replace(regexp, 'm') // mm name is Syoyu str.replace(regexp1, 'm') // mm name is Smomu console.log(str) // my name is Syoyu
替换与正则表达式匹配的子串,返回替换后的值,原始值不变。在不设置全局匹配g的时候,只替换第一个匹配成功的字符串片段
let str = 'my name is Syoyu' let regexp = /y/ let regexp1 = /y/g str.replaceAll(regexp, 'm') // String.prototype.replaceAll called with a non-global RegExp argument str.replaceAll(regexp1, 'm') // mm name is Smomu str.replaceAll('y', 'm') // mm name is Smomu console.log(str) // my name is Syoyu
替换与正则表达式匹配的所有子串,返回替换后的值,原始值不变。
当regexp是字符串时,匹配所有字串;当regexp是正则表达式时,必须加上g修饰符,否则会报错
let str = 'my name is Syoyu' let regexp = /y/ let regexp1 = /y/g str.match(regexp) // ['y', index: 1, input: 'my name is Syoyu', groups: undefined] str.match(regexp1) // ['y', 'y', 'y'] str.macth(/b/) // null
找到一个或多个正则表达式的匹配, 它返回一个数组,在未匹配到时会返回 null
如果 regexp 不带有 g 标记,则它以数组的形式返回第一个匹配项
如果 regexp 带有 g 标记,则它将所有匹配项的数组作为字符串返回,而不包含分组和其他详细信息
let str = 'my name is Syoyu' let regexp = /y/ let regexp1 = /y/g str.matchAll(regexp, 'm') // String.prototype.replaceAll called with a non-global RegExp argument str.matchAll(regexp1, 'm') // RegExpStringIterator {} [...str.matchAll(regexp1, 'm')] // [Array(1), Array(1), Array(1)] [...str.matchAll(regexp1, 'm')][0] // ['y', index: 1, input: 'my name is Syoyu', groups: undefined] [...str.matchAll(regexp1, 'm')][1] // ['y', index: 12, input: 'my name is Syoyu', groups: undefined] [...str.matchAll(regexp1, 'm')][2] // ['y', index: 14, input: 'my name is Syoyu', groups: undefined]
返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。
当regexp是字符串时,匹配所有字串;当regexp是正则表达式时,必须加上g修饰符,否则会报错
let str = 'my name is Syoyu' let regexp = /y/ str.search(regexp) // 1 第一个匹配项的位置
返回第一个匹配项的位置,如果未找到,则返回 -1
let str = 'my name is Syoyu' let regexp = /\s/ str.search(regexp) // ['my', 'name', 'is', 'Syoyu']
使用正则表达式(或子字符串)作为分隔符来分割字符串
说明 | 贪婪匹配量词符 |
---|---|
*, +, ?, {n,}, {n, m} | 非贪婪匹配量词符 |
*?, +?, ??, {n,}?, {n, m}? |
let regexp = /my{1,3}name/
尽可能多的匹配,例如下面的列子
let str = 'my name is Syoyu' let regexp = /(\D{1,5})(\D+)/ str.match(regexp) // ['my name is Syoyu', 'my na', 'me is Syoyu', index: 0, input: 'my name is Syoyu', groups: undefined]
在匹配的时候,尝试匹配的顺序是从多往少的方向去匹配的。首先尝试yyy,然后再看整个正则能否匹配上,如果不能匹配上,则开始尝试yy,以此往复。
如果多个贪婪量词挨在一起,则深度优先搜索
其中,\D{1,5} 匹配的是’my na’,\D+ 匹配的是’me is Syoyu’
let str = 'my name is Syoyu' let regexp = /(\D{1,5}?)(\D+?)/ str.match(regexp) // ['my', 'm', 'y', index: 0, input: 'my name is Syoyu', groups: undefined]
惰性量词就是在贪婪量词后面加个问号,表示尽可能少的匹配
其中,\D{1,5}? 匹配的是 ‘m’,\D+? 匹配的是 'y’
let str = 'Syoyu' let regexp = /(\D{1,2})(\D+)/ str.replace(regexp, ' ') // 'oyu Sy'
分组主要是用过()进行实现,Syoyu{3},是匹配u字母3次。而(Syoyu){3}是匹配Syoyu三次
列入下面代码反向引用,巧用$分组捕获
上面代码中 Sy 和 oyu 交换了位置
说明 | (?:pattern) |
---|---|
例如, 'industr(?:y|ies)‘就是一个比’industry|industries’ 更简略的表达式。 | (?=pattern) |
正向肯定预查(look ahead positive assert)。 例如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。 | (?!pattern) |
正向否定预查(negative assert)。 例如,“Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows”。 | (?<=pattern) |
反向(look behind)肯定预查。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。 | (? |
反向否定预查。 例如"(?6 应用场景 |
通过上面的内容,我们对正则表达式有了一定的了解
下面我们来看一看正则表达式的一些实际应用案列:
/^[a-zA-Z0-9_-]{4,16}$/
/^1[34578]\d{9}$/
/^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }成都网站制作网页
function numFormat(num) { return num.toString().replace(/\d+/, function(n) { retrun n.replace(/(\d)(?=(\d{3})+$)/g, function($1) { return $1 + ',' }) }) }