正则表达式 基础用法

为什么需要正则呢?

将给定的数字转化成千分位的格式,如把“10000”转化为“10,000”

// js逻辑写法
function transform(num) {
  num = (num + '').split('')
  ı
  var temp = []
  var count = 0;
  
  for (var len = num.length, i = len - 1; i >= 0; i--) {
    temp.unshift(num[i])
    count+=1
    if(count % 3 === 0 && i != 0) {
      temp.unshift(',')
   } 
 }
  return temp.join('')
}
// 正则写法 
function transform(num) {    
    num = num + '';
    return num.replace(/(?=(?!\b)(\d{3})+$)/g, ',');
}
  • 定义方式

var reg = /(?=(?!\b)(\d{3})+$)/g // 对象字面量声明 /pattern/flag

var reg = new RegExp('(?=(?!\\b)(\\d{3})+$)', 'g') // 构造函数声明正则,其实就是去掉了两边的 / 而且里面的每个 \ 都要转义
  • 打印方式

  • RegExp 对象

方法

  • test() 返回 true 或者 false

  • exec() 返回一个类数组,其实是个对象,返回的结果中的 "0" 项是完全匹配的字符串,一般没什么用,但 "1" 项会返回捕获分组的结果就很有用

属性

  • source 返回当前正则表达式对象的模式文本的字符串不包含 // 和 标志位

  • ignoreCase 标志位 i 忽略大小写

  • global 标志位 g 全局匹配 用 string.match() 可以拿出所有匹配的字符串

  • multiline 标志位 m 有换行符 \n 可以匹配多行

  • 基本语法

开头

^匹配字符串的开始$匹配字符串的结束

量词

等价于{ 0, 1 },表示出现或者不出现+等价于{ 1, } ,表示出现至少一次
*等价于{ 0, } ,表示出现任意次,有可能不出现{ m }等价于{ m, m },表示出现m次 
{ m, }表示至少出现m次   

常见简写

\w匹配字母或数组或下划线的字符 [0-9a-zA-Z_] 英文:word\W匹配不是字母,数字,下划线的字符  [^ 0-9a-zA-Z]
\d匹配数字 [0-9] 英文:digit\D匹配非数字的字符  [^ 0-9]
\s匹配任意空白符 [ \t\v\n\r\f] 英文:space\S匹配不是空白符的字符  [^ \t\v\n\r\f]
\b匹配单词的开始或结束的位置\B匹配不是单词开头或结束的位置

[abc]

一个字符集abc,匹配包含abc中任意的字符

[^xyz]

一个否定字符集,匹配不包含abc中任意的字符

[\d\D][\w\W][\s\S][^]匹配任意字符  

其他

\b\W和\w 的边界\B\w\w\W\W^\W\W$之间的位置
?=p字符p前面的位置?!p非字符p前面的位置
 
  • 贪婪匹配和惰性匹配

var regex = /\d{2,5}/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) ); 
// => ["123", "1234", "12345", "12345"]

其中正则/\d{2,5}/,表示数字连续出现2到5次。会匹配2位、3位、4位、5位连续数字。

但是其是贪婪的,它会尽可能多的匹配。你能给我6个,我就要5个。你能给我3个,我就3要个。反正只要在能力范围内,越多越好。

我们知道有时贪婪不是一件好事(请看文章最后一个例子)。而惰性匹配,就是尽可能少的匹配:

var regex = /\d{2,5}?/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) ); 
// => ["12", "12", "34", "12", "34", "12", "34", "56"]


其中/\d{2,5}?/表示,虽然2到5次都行,当2个就够的时候,就不在往下尝试了。

通过在量词后面加个问号就能实现惰性匹配,因此所有惰性匹配情形如下:

{m,n}?
{m,}?
??
+?
*?

 

 

  • 多选分支

一个模式可以实现横向和纵向模糊匹配。而多选分支可以支持多个子模式任选其一。

具体形式如下:(p1|p2|p3),其中p1p2p3是子模式,用|(管道符)分隔,表示其中任何之一。

例如要匹配"good"和"nice"可以使用/good|nice/。测试如下:

var regex = /good|nice/g;
var string = "good idea, nice try.";
console.log( string.match(regex) ); 
// => ["good", "nice"]

但有个事实我们应该注意,比如我用/good|goodbye/,去匹配"goodbye"字符串时,结果是"good":

var regex = /good|goodbye/g;
var string = "goodbye";
console.log( string.match(regex) ); 
// => ["good"]

而把正则改成/goodbye|good/,结果是:

var regex = /goodbye|good/g;
var string = "goodbye";
console.log( string.match(regex) ); 
// => ["goodbye"]

也就是说,分支结构也是惰性的,即当前面的匹配上了,后面的就不再尝试了。

 

  • 常用例子

匹配邮箱的正则

var str = 'https://qq.com/'
var reg = /^https?:\/\/q{2}\.com\/$/g

console.log(reg.test(str)) // true
console.log(str.match(reg)) // ["https://qq.com/"]
console.log(reg.exec(str)) // ["https://qq.com/", index: 0, input: "https://qq.com/", groups: undefined]

 

匹配日期

比如yyyy-mm-dd格式为例。

要求匹配:

2017-06-10

分析:

年,四位数字即可,可用[0-9]{4}

月,共12个月,分两种情况01、02、……、09和10、11、12,可用(0[1-9]|1[0-2])

日,最大31天,可用(0[1-9]|[12][0-9]|3[01])

正则如下:

var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
console.log( regex.test("2017-06-10") ); 
// => true

 

匹配id

要求从

<div id="container" class="main"></div>

提取出id="container"。

可能最开始想到的正则是:

var regex = /id=".*"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]); 
// => id="container" class="main"

因为.是通配符,本身就匹配双引号的,而量词*又是贪婪的,当遇到container后面双引号时,不会停下来,会继续匹配,直到遇到最后一个双引号为止。

解决之道,可以使用惰性匹配:

var regex = /id=".*?"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]); 
// => id="container"

var regex = /id=".*?"/
var string = '<div id="container" id="test" class="main"></div>';
console.log(string.match(regex)); 
// => ["id="container"","id="test""]

 

数字的千位分隔符表示法

比如把"12345678",变成"12,345,678"。

可见是需要把相应的位置替换成","。

思路是什么呢?

  • 弄出最后一个逗号

使用(?=\d{3}$)就可以做到:

var result = "12345678".replace(/(?=\d{3}$)/g, ',')
console.log(result); 
// => "12345,678"
  • 弄出所有的逗号

因为逗号出现的位置,要求后面3个数字一组,也就是\d{3}至少出现一次。

此时可以使用量词+

var result = "12345678".replace(/(?=(\d{3})+$)/g, ',')
console.log(result); 
// => "12,345,678"
  • 匹配其余案例

写完正则后,要多验证几个案例,此时我们会发现问题:

var result = "123456789".replace(/(?=(\d{3})+$)/g, ',')
console.log(result); 
// => ",123,456,789"

因为上面的正则,仅仅表示把从结尾向前数,一但是3的倍数,就把其前面的位置替换成逗号。因此才会出现这个问题。

怎么解决呢?我们要求匹配的到这个位置不能是开头。

我们知道匹配开头可以使用^,但要求这个位置不是开头怎么办?

easy,(?!^),你想到了吗?测试如下:

var string1 = "12345678",
string2 = "123456789";
reg = /(?!^)(?=(\d{3})+$)/g;

var result = string1.replace(reg, ',')
console.log(result); 
// => "12,345,678"

result = string2.replace(reg, ',');
console.log(result); 
// => "123,456,789"

4.2.4 支持其他形式

如果要把"12345678 123456789"替换成"12,345,678 123,456,789"。

此时我们需要修改正则,把里面的开头^和结尾$,替换成\b

var string = "12345678 123456789",
reg = /(?!\b)(?=(\d{3})+\b)/g;

var result = string.replace(reg, ',')
console.log(result); 
// => "12,345,678 123,456,789"

其中(?!\b)怎么理解呢?

要求当前是一个位置,但不是\b前面的位置,其实(?!\b)说的就是\B

因此最终正则变成了:/\B(?=(\d{3})+\b)/g

 

 

参考文章:

JS正则表达式完整教程(略长)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值