美文网首页
前端的正则表达式

前端的正则表达式

作者: 鱼仔1234 | 来源:发表于2018-11-26 19:46 被阅读0次

正则的用法

  const regex = /abc/g
  const regex2 = new RegExp('abc', 'g')
  regex 和 regex2的匹配内容是一样的,都是全局匹配abc字符串,
  只不过regex是用正则表达式字面量,而regex2是调用RegExp构造函数写法。

元字符

^   匹配字符串的开始               /^a/ 表示匹配以a开始
$   匹配字符串的结尾               /a$/ 表示匹配以a结尾
\d  [0-9] 表示0-9的任意一位数字    /^\d/ 表示以一个数字开始
\D  [^0-9] 表示除数字外的任意字符   /^\D/ 表示不能以数字开始
\w  [0-9a-zA-Z_] 表示数字、大小写字母和下划线
\W  [^0-9a-zA-Z_] 表示非单词字符
\s  [\t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页符
\S  [^ \t\v\n\r\f] 非空白符
\b  匹配一个单词边界
\B  匹配非单词边界
.   [^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。
    要是想匹配字符串.需要转译\.

量词

{m, n} 出现了m-n次
{m}    出现了m次
{m,}   出现了至少mci
{,n}   最多出现了n次
?     出现了0次或1次, 等价于{0,1}
+      最少出现了1次,等价于{1,}
*      出现0次或多次,等价于{0,}

贪婪与惰性

贪婪就是尽可能多的匹配,而惰性就是尽可能少的匹配

贪婪匹配写法:量词后面加个*
惰性匹配写法:量词后面加个?

/.*bbb/g.exec('abbbaabbbaaabbb1234')  // abbbaabbbaaabbb
/.*?bbb/g.exec('abbbaabbbaaabbb1234') // abbb

贪婪模式用于匹配优先量词修饰的子表达式
惰性模式用于匹配忽略优先量词修饰子表达式

分组

正则中一对()即为一个分组

/(abx).*/.test('abxsss') 其中(abx) 就是一个分组

可使用构造函数的全局属性1至9来获取

/(abx).*/.exec('abxsss')
console.log(RegExp.$1)  // abx
console.log(RegExp.$_)  // abxsss

只能表示到1-9, 如果分组超过了九组,那就没法表示了

反向引用

/\d{4}(-|\/|\.)\d{2}\1\d{2}/
注意里面的\1,表示的引用之前的那个分组(-|\/|\.)。
不管它匹配到什么(比如-),\1都匹配那个同样的具体某个字符。
我们知道了\1的含义后,那么\2和\3的概念也就理解了,即分别指代第二个和第三个分组。

这里的分组只是在此之前的分组,在该反向引用之后的无法表示。
/\d{4}(-|\/|\.)\d{2}\2(\d{2})/
这里不能用\2来引用(\d{2})分组,这里只是当作匹配\2去匹配,而不是当作分组的引用

具名分组

/(\d{4}(-|\/|\.))\d{2}\2\d{2}/
这里的第二个分组应该是(-|\/|\.)

那/^((\d)(\d(\d)))$/的分组又是怎么分的呢?
对于过多括号嵌套情况,分清分组比较容易出错
括号嵌套的分组,应该从第一个(往里面数,每遇到一个(就是一个新的分组

具名分组就很好的解决了这个问题
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
这里就是用到了具名分组
可以通过\k<month>引用具体是哪个分组
/(?<year>\d{4})-(?<month>\d{2})-\k<month>/
具名分组结果会放在group属性里面

非捕获分组

也可以通过非捕获分组来降低分组的复杂度。非捕获分组是指不会将(?:)中的正则化为一个分组。
/^(?:(?:\d)(\d(\d)))\2$/
这里\2引用的分组是(\d)

零宽断言(环视)和负零宽断言

/z(?=x)y/ 表示z后面紧跟着的是x,但是不匹配x
/z(?!x)y/ 表示z后面紧跟着的不是x,但是不匹配x

/z(?<=x)y/ 表示y前面紧跟着的是x,但是不匹配x
/z(?<!x)y/ 表示y前面紧跟着的不是x,但是不匹配x


修饰符

1. g → global 全局搜索
2. i → ignoreCase 忽略大小写,大小写不敏感
3. m → multiline 换行
4. y → sticky  “粘连”修饰符  后一次匹配都从上一次匹配成功的下一个位置开始
5. u → unicode Unicode 字符表示法

lastIndex

是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。
只有正则表达式使用了表示全局检索的 "g" 标志时,该属性才会起作用。此时应用下面的规则:

如果 lastIndex 大于字符串的长度,则 regexp.test 和 regexp.exec 将会匹配失败,然后 lastIndex 被设置为 0。
如果 lastIndex 等于字符串的长度,且该正则表达式匹配空字符串,则该正则表达式匹配从 lastIndex 开始的字符串。(then the regular expression matches input starting at lastIndex.)
如果 lastIndex 等于字符串的长度,且该正则表达式不匹配空字符串 ,则该正则表达式不匹配字符串,lastIndex 被设置为 0.。
否则,lastIndex 被设置为紧随最近一次成功匹配的下一个位置。

练习


1.检测是否满足
  2016-06-12
  2016/06/12
  2016.06.12
  这三种格式


/\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/.test('2012/12/13')
这样写有一个问题,那就是
/\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/.test('2012/12-13') 也是true

所以这里就得用到分组引用了
/\d{4}(-|\/|\.)\d{2}\1\d{2}/.test('2012/12-13') false
/\d{4}(-|\/|\.)\d{2}\1\d{2}/.test('2012/12/13') true
这里的\1指的是第一个分组匹配到了什么,这里就是什么


2.将 2016/12/04 改为 12/04/2016
传统做法可能是需要先以'/'分割字符串,然后在就行字符串拼接
现在可以这样写

'2016/12/04'.replace(/(\d{4})\/(\d{2})\/(\d{2})/, '$2/$3/$1')

或者

'2016/12/04'.replace(/(\d{4})\/(\d{2})\/(\d{2})/, function(...arg) {
  return arg[2]+'/' + arg[3]+'/' + arg[1]
})

let result = /(?<year>\d{4})\/(?<month>\d{2})\/(?<day>\d{2})/.exec('2016/12/04')
console.log(result)
// 0: "2016/12/04"
// 1: "2016"
// 2: "12"
// 3: "04"
// groups:
//  day: "04"
//  month: "12"
//  year: "2016"
// index: 0
// input: "2016/12/04" 


3.可以正确筛选以下规则
'x=5'           5
'abcx=5'        5
'abc x=5'       5
'x=abc'         null

str.match(/(?<=x=)\d+/)

4.可以正确筛选以下规则
'x=5'           5
'abcx=5'        null
'abc x=5'       5
'x=abc'         null
这个和上面的区别就在于x=之前是不是一个边界
str.match(/(?<=\bx=)\d+/)
不可以用一下的正则匹配
str.match(/(?<=\s+x=)\d+/)
因为这样的话'x=5'就不匹配了

5.可以正确筛选以下规则
'one "two three" four five six "seven eight" nine' 
to 
'"two three" four five six "seven eight"'

str.match(/".*"/g)

6.可以正确筛选以下规则
'one "two three" four five six "seven eight" nine' 
to 
['"two three"', '"seven eight"']

str.match(/".*?"/g)
这里和上面的区别就在于一个是贪婪匹配而这个是惰性匹配

7.可以正确筛选以下规则
'@@whatever@@@@whatever2@@' 
to
 '<blink>whatever</blink><blink>whatever2</blink>'

str.replace(/(@@)(.*?)(@@)/g, function(...arg) {
  return '<blink>'+ arg[2]+'</blink>'
})
这里不能简单的将'@@'替换成'<blink>',因为'@@'必须是成对出现的

8.可以正确筛选以下规则
var text = "First line\nsecond line";
var regex = /(\S+) line\n?/y;

var match = regex.exec(text);
match[1];  // "First"

var match2 = regex.exec(text);
match2[1]// "Second"

var match3 = regex.exec(text);
match3 === null //"true"
这里是开启粘滞匹配的一个事例

9.测试以下代码
var re=/^\w$/g
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
...

为什么会出现这种情况呢?
这里就涉及到了lastIndex了,
var re=/^\w$/g
re.lastIndex = 0

re.test('a')  true
这里正则匹配完成后re.lastIndex = 1

re.test('a')  false
因为re.lastIndex = 1了,所以这里的re.test就会失效,当然re.exec也会失效。
可以理解为这时正则是从1这个位置去匹配的,所以匹配不到任何东西.只会就会再次把lastIndex改为0
re.lastIndex = 0

re.test('a')  true
又重新从头开始匹配了,所以这里又再次为true了

结尾

本文并没有举例传统的一下正则,如邮箱格式,手机号码格式等,因为这些正则可以搜到很多。本文主要是用到了一下稍微高阶一点的正则方法。古人云:用好了正则,可以帮我们省下5000行代码。

相关文章

  • vue(2) - 收藏集 - 掘金

    javascript 正则表达式总结 - 前端 - 掘金为什么要使用正则表达式 正则表达式通过由普通字符和特殊字符...

  • ip:port 正则校验

    正则表达式 前端使用的表达式 使用正则表达式在线工具[https://c.runoob.com/front-end...

  • 23-第二十三章 RegExp

    前端常用正则表达式 http://caibaojian.com/form-regexp.html https://...

  • 正则表达式和NFA

    作为前端大佬的你,想必对于 JavaScript 的正则表达式非常熟悉了,甚至随手就能利用正则表达式写出一些惊世骇...

  • JS常用正则表达式备忘录

    摘要: 玩转正则表达式。 原文:JS常用正则表达式备忘录 作者:前端小智 Fundebug经授权转载,版权归原作者...

  • js中的正则表达式

    正则表达式 标签(空格分隔): 前端 1、正则表达式是一个描述字符模式的对象,拥有强大的模式匹配和文本检索与替换功...

  • 前端正则表达式书写以及常用的方法

    前端正则表达式书写 一.写法 写法一 /正则表达式/修饰符 修饰符 /i (忽略大小写) /g (全文查找出现的所...

  • 模板引擎原理

    # 模板引擎 ## 原理 ![模板引擎原理](F:\前端学习资料\模板引擎原理.jpg) ## 使用到的正则表达式...

  • 无标题文章

    # 模板引擎 ## 原理 ![模板引擎原理](F:\前端学习资料\模板引擎原理.jpg) ## 使用到的正则表达式...

  • Java 小技巧

    前端基础(一):字符串String常用操作java中Date日期类型的大小比较Java 正则表达式

网友评论

      本文标题:前端的正则表达式

      本文链接:https://www.haomeiwen.com/subject/psriqqtx.html