javabloger 2019-06-21
为了匹配规定模式的文本
为了守护世界的和平
我们是穿梭在银河的正则表达式
就是这样~喵~
好用的正则表达式可视化工具: https://regexper.com/
//字面量 var regExp1 = /pattern/flags; //或用构造函数 var regExp2 = new RegExp(pattern[, flags]);
pattern
:正则表达式的匹配模式flags
:可选,正则表达式的标识,也可选多个。g
全局匹配,i
忽略大小写,m
匹配多行
一颗超简单的栗子:
var regExp = /abc/; "abcdefg".replace(regExp, "WOW"); // "WOWdefg"
字符 | 举例 | 含义 |
[] | [xyz] | xyz中任意一个字符 等价于[x-z] |
[^] | [^xyz] | 匹配任意不在xyz中的一个字符,等价于[^x-z] (注意与^x区分,后者表示匹配以x开头的字符) |
[-] | [1-3] | 匹配123中的任意一个字符,等价于[123]。注意:连字符只有出现在方括号中才表示连续的字符序列。 |
预定义模式就是某些常用模式的简写。
字符 | 含义 |
. | 除\r和\n之外的任意字符,等价于[^\r\n] |
\d | 数字0-9,等价于[0-9] |
\D | 非数字字符,等价于[^0-9] |
\w | 字母数字下划线,等价于[A-Za-z0-9_] |
\W | 非字母数字下划线,等价于[^A-Za-z0-9_] |
\s | 空白符 |
\S | 非空白符 |
\n | 换行符 |
正则模式中,需要用斜杠转义的:
* + ? $ ^ . | \ ( ) { } [ ]
需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。
字符 | 举例 | 含义 |
^ | ^a | 以a开头(注意与[^]区分,后者表示匹配不在[^]中的元素) |
$ | a$ | 以a结尾 |
\b | \bsmart,smart\b | 单词边界,即[A-Za-z0-9_]之外的字符 |
\B | \Bsmart | 非单词边界 |
举个栗子说 \b 和 \B :
"You are smart, but she is smarter.".replace(/smart\b/,"kind"); //"You are kind, but she is smarter." "You are smart, but she is smarter.".replace(/smart\B/,"kind"); //"You are smart, but she is kinder."
if(看不懂){ 就置几动手试试吧 (ง •̀_•́)ง }
字符 | 含义 |
? | 匹配前面的模式 0或1次 {0,1} |
* | 匹配前面的模式 0或多次 {0,} |
+ | 匹配前面的模式 1或多次 {1,} |
{n} | 匹配前面的模式 n次 |
{n,} | 匹配前面的模式 至少n次 |
{n,m} | 匹配前面的模式 至少n次,至多m次 |
{0,m} | 匹配前面的模式 至多m次 |
x(?=y) | 只有x后面紧跟着y时,才匹配x,但是y不是匹配结果的一部分。例如/smart(?=girl)/ 只有后面有girl 时,才匹配smart ,但是girl 不是匹配结果的一部分。 |
x(?!y) | 只有x后面不紧跟着y时,才匹配x。例如/\d+(?!\.)/ 只有一个数字后面没有紧跟着小数点时才会匹配该数字,/\d+(?!\.)/.exec("3.141") 匹配结果是141 。 |
默认是贪婪模式匹配,即匹配尽可能多的字符。
var regExp1 = /\d{3,6}/; "1234567890".replace(regExp1, "X"); //"X7890"
若想手动开启懒惰模式,需要在模式后加 ?
var regExp1 = /\d{3,6}?/; "1234567890".replace(regExp1, "X"); //"X4567890"
分组又叫“子表达式”,把完整的正则表达式分成一个个小组,然后反过来用“组号”去引用这些小组就叫“反向引用”。
用例子来说:
//无分组 var regExp1 = /abc{2}/; //这样量词{2}只能匹配到c一个字符 //分组 var regExp2 = /(abc){2}/; //这样量词{2}就可以匹配到abc三个字符啦 //同时 abc 也有了一个组号 $1
再看一个栗子:
var reg = /(\d{1}).*(\d{2}).*(\d{3})/; "1sss23sss456".replace(reg,"$1?$2?$3"); //"1?23?456"
上面的栗子换一种使用分组的方式:
var reg = /(\d{1}).*(\d{2}).*(\d{3})/; var result = reg.exec("1sss23sss456"); console.log(result[1]+"-"+result[2]+"-"+result[3]); //"1-23-456"
组匹配非常有用,下面是一个匹配网页标签的例子:
var tagName = /<([^>]+)>[^<]*<\/\1>/; // \1 就是第一个组匹配的内容 tagName.exec("<b>bold</b>")[1]
上面代码稍加修改,就可以捕获带有属性的标签:
var html = '<b class="hello">Hello</b><i>world</i>'; var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g; var match = tag.exec(html); match[1] // "b" match[2] // " class="hello"" match[3] // "Hello" match = tag.exec(html); match[1] // "i" match[2] // "" match[3] // "world"
非捕获组: (?:x)
表示不返回该组匹配的内容,即匹配的结果中不出现这个括号。
测试当前正则是否能匹配目标字符串,返回布尔值。
var reg = /\d{2}/; var str = "1sss23sss456"; reg.test(str); //true
在目标字符串中执行一次正则匹配操作,返回匹配的子字符串。
var reg = /\d{2}/; var str = "1sss23sss456"; var result = reg.exec(str); result[0]; //23 result.index; //4 result.input; //"1sss23sss456"
返回一个字符串,其值为该正则对象的字面量形式。覆盖了Object.prototype.toString() 方法。
var reg = /\d{2}/; reg.toString(); // "/\d{2}/"
返回替换后的值
var reg = /\d{2}/; var str = "1sss23sss456"; str.replace(reg,"?"); //"1sss?sss456"
常用于消除首尾空格:
var str = ' abc def ggg '; str.replace(/^\s+|\s+$/g, ''); // 'abc def ggg'
replace
方法的第二个参数可以使用美元符号来指代所替换的内容:
> $& 指代匹配的子字符串。 > $` 指代匹配结果前面的文本。 > $' 指代匹配结果后面的文本。 > $n 指代匹配成功的第n组内容,n是从1开始的自然数。 > $$ 指代美元符号$。
replace
方法的第二个参数还可以是一个函数,将每一个匹配内容替换为函数的返回值。这个函数可以接受多个参数,第一个参数是捕捉到的内容,第二个参数开始是捕捉到的组匹配(有多少个组匹配,就对应有多少个参数)。此外,最后还可以添加两个参数,倒数第二个是捕捉到的内容在整个字符串中的位置,最后一个参数是原字符串。下面是一个网页模板替换的例子:
var prices = { 'pr_1': '$1.99', 'pr_2': '$7.99', 'pr_3': '$9.99', }; var template = '<span id="pr_1"></span><span id="pr_2"></span>'; template.replace( /(<span id=")(.*?)(">)(<\/span>)/, function(match, p1, p2, p3 ,p4) { return p1 + p2 + p3 + prices[p2] + p4; }); //<span id="pr_1">$1.99</span><span id="pr_2"></span>
注意:第二个分组要加 ?
开启懒惰模式,否则正则表达式默认的贪婪模式会匹配尽可能多的字符。贪婪模式下,上面的例子中第二个分组会匹配到pr_1"></span><span id="pr_2
这一长串,从而无法匹配到我们希望的字符串。
与exec()
类似,返回匹配的子字符串。
var reg = /\d{2}/; var str = "1sss23sss456"; str.match(reg); //["23"]
与exec()
的区别在于:当正则表达式加了g标识符时,结果不同。看栗子:
var reg = /\d{2}/g; var str = "1sss23sss456"; reg.exec(str); //["23"] str.match(reg); //["23","45"]
返回匹配的首字符的位置。
var reg = /\d{2}/; var str = "1sss23sss456"; str.search(reg); //4
返回分割后的数组。
var reg = /\d{2}/; var str = "1sss23sss456"; str.split(reg); //["1sss","sss","6"]
写一个匹配手机号的正则(第一位是1,第二位是[3,4,5,7,8]中的一个,后面还有9位数字)
写一个匹配 2017-01-01 或 2017/01/01 这两种格式日期的正则表达式
————答案:
/^1[34578]\d{9}$/
/^\d{4}[-/]\d{2}[-/]\d{2}$/
var re = /(\w+)\s(\w+)/; var str = "John Smith"; var newstr = str.replace(re, "$2, $1"); console.log(newstr); //Smith, John
var s = "Please yes\nmake my day!"; s.match(/yes.*day/); // null s.match(/yes[^]*day/); //'yes\nmake my day'
var url = "http://xxx.domain.com"; console.log(/[^.]+/.exec(url)[0]); // "http://xxx" console.log(/[^.]+/.exec(url)[0].substr(7)); // "xxx"
匹配除了.之外的任意元素,一到多个字符。
参考: