正则表达式必知必会-读书笔记

什么是正则表达式

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

简单的说,正则表达式是一些用来匹配和处理文本的字符串.利用正则表达式我们可以查找特定的信息,或者替换掉文本中的特定信息.

并且正则表达式搜索的能力和替换文本的能力极为强大,而且其也比较容易学习和掌握.

那么正则表达式是什么样子的,有什么规则,又该如何使用呢?如下面这样的语句:

注:所有举例都是选用javascript编程语言中的正则表达式,所有可能会与其他编程的正则表达式有些出入

 /b[Cc][Aa]/

这就是一个正则表达式,它可以匹配bca,bCa,bcA,bCA这些字符串.所以我想现在你应该对于正则表达式有些概念了.

接下来我们来介绍一些正则表达式的规则和语法.

正则表达式

正则表达语法结构

正则表达式的语法结构如下:

/正则表达式主体/修饰符(可选)

我们来举一个实例来分析一下

/runoob/i

/runoob/i 是一个正则表达式。

runoob 是一个正则表达式主体 (用于检索)。

i 是一个修饰符 (搜索不区分大小写)。

所以该正则表达式可以匹配Runoob,rUnoob等不区分大小写的内容符合runoob的字符串集.

正则表达式修饰符

修饰符是影响整个正则规则的特殊符号,会对匹配结果和部分内置函数行为产生不同的效果,JavaScript正则表达式中,包含以下三个修饰符:

修饰符 描述
i 执行对大小写不敏感的匹配
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止
m 执行多行匹配

匹配单个任意字符

在正则表达式里,我们用.符号来匹配任何一个单个的字符. 例:


var str1 = 'ab'
var str2 = 'a.b'
var str3 = 'acb'
var str4 = 'ac.b'
var reg = /a.b/

console.log(reg.test(str1)) //-> false
console.log(reg.test(str2)) //-> ture 
console.log(reg.test(str3)) //-> true
console.log(reg.test(str4)) //-> false

匹配特殊字符

从上个例子中,我们了解到.字符在正则表达式里有着特殊的含义. 如果我们的模式里需要一个.那该怎么办?

这时,我们可以在.加上\(反斜杠)字符来对它进行转义,使得.表示的是它自身的文本内容,而不是它在正则表达式中的特殊含义.例:

  
var str1 = 'baidu.com' 
var str2 = 'baidu@com'

var reg1 = /baidu\.com/
var reg2 = /baidu.com/
 
console.log(reg1.test(str1))  // -> true
console.log(reg1.test(str2))  // -> false  分析:  字符`@`与字符'.'不匹配 

console.log(reg2.test(str1))  // -> true  分析:  `.`可以匹配任意一个字符, 包括'.'字符本身.
console.log(reg2.test(str2))  // -> true

.一样,/也是一个特殊字符, 如果你想要匹配/内容本身,应该用//来表示.除此,正则表达式中还有很多特殊字符,我们会在下面慢慢介绍.

匹配字符区间(一组字符)中的某一个

  • []的使用

在正则表达式中,我们可以使用元字符[]来定义一个字符集合. 这两个元字符之间的所有字符都是该集合的组成部分.字符集合的匹配结果是能够与该集合里的任意一个成员相匹配的文本.例:

// 写一个正则表达式可以匹配'ca.xls'和'na.xls'.
var reg  = /[cn]a.xls/
// 列举几个字符串来验证正则
var s1 = 'ca.xls'
var s2 = 'na.xls'
var s3 = 'sa.xls'
 
console.log(reg.test(s1)) // -> true
console.log(reg.test(s2)) // -> true
console.log(reg.test(s3)) // -> false
  • 数字字母区间
/[0123456789]/ 

上述正则表达式可以用来匹配0到9这个10个数字中任意一个.

  • 字母字符区间
/[abcdefg]/

上述正则表达式可以用来匹配a-g字符中任意一个字符.

  • 简化写法

上述正则表达式虽然可以表达一些字符区间,但是其写法有些繁琐.为此,正则表达式中提供了一些简化的写法:

区间 说明
[0-9] 匹配0到9之间的数字.
[A-Z] 匹配A到Z之间的所有大写字母.
[a-z] 匹配a到z之间的所有小写字母.
[A-F] 匹配A到F之间的所有大写字母.
[a-f] 匹配a到f之间的所有小写字母.
[A-z] 匹配ASCII字符A到ASCII字符z的所有字母.(不过不常用,因为其中还包含[^等排列在Za之间的字符)

提示:在定义一个字符区间的时候,一定要避免让这个区间的尾字符小于它的首字符. 例如 [3-1]这种区间就是没有意义的,而且往往会让整个模式失效

  • 取非匹配

字符集合通常用来指定一组必须匹配其中之一的字符. 但是有时候我们需要翻过来做,给出一组不需要得到的字符.这时,我们可以用元字符^来对一个字符集合进行取非匹配. 例:

var reg = /[^0-9]/ 
var str1 = '1'
var str2 = 'a'

console.log(reg.test(str1)) // -> false
console.log(reg.test(str2)) // -> true

这个正则表达式匹配的是任何不是数字的字符.

提示: 我们可以把取非理解成数学中的获取补集

类元字符

字符集合(匹配多个字符中的某一个)是最常见的匹配的形式,而一些常用的字符集合可以用特殊元字符来代替可以用特殊元字符来代替.这些元字符匹配的是某一类别的字符(术语称之为'类元字符').类元字符并不是必不可少的东西,但用它们构造出来的正则表达式简明易懂,在实践中很有用.

  • 匹配数字(与非数字)

之前我们介绍过,[0-9]是[0123456789]的简写形式,它可以用来匹配任何一个数字.不过你若是想匹配的除数字以外的其他东西,那么对这个集合取写成[^0-9]便可以了.下面我们列出了用来匹配数字和非数字的类元字符.

元字符 说明
\d 任何一个数字字符(等价于[ 0-9 ])
\D 任何一个非数字字符(等价于[ ^ 0-9 ] )

例:

var reg = /\d/
var str1 = '7'
var str2 = 'a'

console.log(reg.test(str1)) // ->true
console.log(reg.test(str2)) // -> false
console.log(/\D/.test(str2)) // -> true
  • 匹配字母和数字

字母和数字---A到Z(不区分大小写),数字0到9,再加上下划线字符_是另一种比较常用的字符集合;这些字符 常见于各种名字里(如目录名,变量名等等). 其类元字符如下:

元字符 说明
\w 任何一个字母数字字符(大小写均可)或下划线字符(等价于[a-zA-Z0-9_])
\W 任何一个非字母数字字符(大小写均可)或下划线字符(等价于[^ a-zA-Z0-9_])

个人认为\w中的w可能word这个单词的简写,所以我跟喜欢称\w为单词字符.
例:

var reg = /\w+/
var str1 = 'abc123_'
var str2 = '-;~@'

console.log(reg.test(str1)) // ->true
console.log(reg.test(str2)) // -> false
console.log(/\W+/.test(str2)) // -> true

匹配空白字符

在介绍如何匹配空白字符,我们先来说一些小常识.

  1. 回车与换行

    • 回车的转义字符是/r , 回车是光标回到当前行的开始位置.
    • 换行的转义字符是/n, 换行是光标转到当前位置的下一行相同的位置.

因此,在DOS和WINDOWS系统上,回车和换行必须连用,从而实现文 本字符的换行并回到下一行的起始位置.包括HTTP也使用CRLF来表示 每一行的结束.

而在UNIX,LINUX中,只有换行码而不需要回车码,系统默认换行就是回车加换行。

但是,在MAC上,Mac OS 9 以及之前的系统的换行符是CR\r ,从 Mac OS X (后来改名为“OS X”)开始的换行符是 LF\n,和Unix/Linux统一了。

  1. 如何表示一个空白行

在Windows中用\r\n\r\n来代表一个空白行.而在Linux中用\n\n来代表一个空白行.

我们可以用正则表达式[\r]?\n[\r]?\n来匹配不同系统中的一个空白行.

关于空白行的匹配,我想你也许会有这样一个疑问: 遇到\r\n\n或者\n\r\n\这两种情况,该如何? 如果遇见这两种情况的话的确会被上述正则表达式所匹配.但是一般情况下,这两种情况极为少见(通常只有人为的拼接换行符时才会出现这种情况).所以你可以安心使用,如果你还觉得不放心的话,可以用/[(\r\n\r\n)(\n\n)]/来匹配空白行.

  1. 空格和空白字符

    其实空格只是字符中的一种,它并不是转义字符. ' '这便是空格字符的表示方法.
    下面是一个用正则来验证空格字符的:

     var str = 'hello world'
     var str2 = 'helloworld'
     var reg = / /
     console.log(reg.test(str))  // -> true
     console.log(reg.test(str2)) // -> false
    

    但是在正则表达式中可以用\s来匹配空白字符.需要注意的是空白字符并不等同于空格字符,或者说空格字符是空白字符的一个成员.空白字符有:

    字符 说明
    \n 换行字符
    \f 换页符
    \r 回车符号
    \t 制表符
    \v 垂直制表符
    " " 空格(js中的特有的)
 因此上述代码也可以改为如下:
 
```js
var str = 'hello world'
var str2 = 'helloworld'
var reg = /\s/
console.log('str',reg.test(str),'str2',reg.test(str2))
// str true str2 false
```

匹配十六进制和八进制

  • 十六进制

我们可以用前缀\x来匹配十六进制值. 例如\x0A对ASCII中的序号为10的符号(换行符),其效果等价于\n.

  • 八进�制

我们用前缀\0来匹配八进制值.例如\011对应于ASCII中的序号为9的符号(制表符),其效果等价于\t.

重复匹配

  • 匹配一个或多个字符

我们可以给字符(或者字符集合)加上一个+作为后缀,来匹配一个或多个(至少一个,不匹配0个字符的情况)字符.


var reg = /ba+/ 
// 匹配 "baaa","ba", 但不匹配"b".

var reg = /[0-9]+/
//匹配任意数字串的组合.

var reg = /[0-9+]/
/*
 这样写�虽然是合法正则式,但是不能匹配一个或者多个数字.
 它代表的是 [0123456789+]这个集合中的任意一个字符.
*/
  • 匹配零个或多个字符

我们可以给字符(或者字符集合)加上一个*作为后缀,来匹配零个或多个字符. 例:

var reg = /ba*/
var str1 = 'baaaa'
var str2 = 'b'

console.log(reg.test(str1)) // -> ture
console.log(reg.test(str2)) // -> ture
  • 匹配零个或者一个字符

我们可以给字符(或者字符集合)加上一个?作为后缀,来匹配零个或多个字符.例:

// 匹配http或者https,可以用如下正则表达式
var reg = /http[s]?/ // => http或者https
// 匹配不同系统中的空白行
reg = /[\r]?\n[\r]?\n/ //=> \r\n\r\n 或者\n\n
  • 匹配的重复次数

    我们可用用{}符号来为重复匹配设定重复次数.

    • 为重复匹配次数设定一个精确的值
  var  reg =  /#[0-9A-Fa-f]{6}/  // 可以用来匹配任意一个RGB值.
  reg.test('#486D3A') // true
  reg.test('#3F3F46') // true
  reg.test('#3F3F4')) //false
  • 为重复匹配次数设定一个区间
    {}还可以用来为为重复匹配次数设定一个区间.如{2,4}这样的形式,代表的含义是最少重复两次,最多重复4次.
   var reg = /\d{2,4}/ 
   reg.test('1') // -> false 
   reg.test('12') // -> true
   reg.test('1234') // -> true

{3,}表示至少重复3次. 如:

 var reg=/\d{3,}/
 reg.test('1') // -> false 
 reg.test('1234') // -> true

防止过度匹配

我们利用正则表达式来获取文本中的a标签,如下例:

var str = ' this offer is not available to customers living in <a>AK</a> and <a>HI</a>'

var reg = /<a>.*<\/a>/g 

str.match(reg)  // 匹配结果: <a>AK</a> and <a>HI</a>

我们发现虽然没有漏掉我们想要匹配的文本,但是并不是我们预期的结果, 我们想要的结果是分别返回两个标签,而不是一个包含两个标签的文本.

这是因为,*+都是所谓的贪婪型元字符,它们进行匹配时的行为模式是多多益善而不是适可而止的.它会尽可能的从一段文本的开头一直匹配到这段文本的结尾,而不是从这段文本的开头到到第一个匹配时为止.

那么问题来了,如果我们不需要这种贪婪行为�,该怎么办呢?答案便是用这些元字符懒惰版本.即匹配尽可能少的字符.下面是几个常用的贪婪型元字符和它的懒惰版本:

贪婪型元字符 懒惰型元字符
* *?
+ +?
{n,} {n,}?

现在我们修改上一次的代码,使它达到我们的预期.

var str = ' this offer is not available to customers living in <a>AK</a> and <a>HI</a>'
var reg = /<a>.*?<\/a>/g 
 str.match(reg)  // 匹配结果: ["<a>AK</a>", "<a>HI</a>"]

我们应根据具体情况来选用'贪婪型'或'懒惰型'元字符.

位置匹配

在某些场合中,我们需要对某段文本的特定位置进行匹配,这是就需要使用位置匹配来解决了.

提示:位置匹配符,只匹配位置而不匹配内容.这点极为重要,需要牢记

  • 单词边界

我们用限定符\b(boundary)来指定单词的边界,\b可以用来匹配一个单词的开头或结尾.

\b匹配的是这样一个位置: 这个位置位于一个能够用来构成单词的字符(字母,数字以及下划线.即\w)和一个不能用来够成单词的字符(即\W)之间.

我们可以用|来模拟边界符,为字符串"the captain wore his cap and cape proundly"

结果如下:

|the| |captain| |wore| |his| |cap| |and| |cape| |proundly|

如果到这里你对与这个单词边界符\b还有些疑惑. 我们可以再举个例子:

 字符串: "baidu.com" 

我们知道上述字符串中的.并不在\w中.所以我们认为它是一个非单词字符.而.两边分别是字母u和字母c,它们都属于\w,都是单词字符.

如上述的关于单词边界的定义解释一样,单词边界是一个能够用来构成单词的字符(字母,数字以及下划线.即\w)和一个不能用来够成单词的字符(即\W)之间的位置.我们为字符串加上边界,如下:

|baidu|.|com

单词字符非单词字符之间的位置就是单词边界.

接下来我们来看看一个使用\b的例子:

var str1 = 'and cap  proundly '
var str2 = 'and cape  proundly '
 
var reg= /\bcap\b/

// 匹配字符串是否有"cap"这个单词
console.log(reg.test(str1)) // -> true 
console.log(reg.test(str2)) // -> false
  • 字符串边界

字符串边界可以用来进行与字符串有关的�位置匹配(字符串的开头,结尾,等等.)

  1. ^匹配字符串的开头

我们用^来匹配一个字符串的开头位置.用法如下:

  var str1 = 'I will persist until I succeed.'
  var str2 = 'You will persist until I succeed.'
  
  var reg = /^I.*?/

  reg.test(str1) // true
  reg.test(str2) //false

^是几个有着多种用途的元字符之一,只有当它出现在一个字符集合里并且紧跟[之后,才能表现出"求非"的作用.如果是在一个字符集合外面并且位于一个模式的开头,^将匹配一个字符�串的开头.

  1. $匹配字符串的结尾

^的使用方法类似,我们用$来匹配字符串的结尾.用法如下:

  var str1 = 'I will persist until I succeed'
  var str2 = 'I will persist until I have  success'
  
  var reg = /s$/

  reg.test(str1) // -> false
  reg.test(str2) // -> true

接下来,我来说一种特殊的情况,就是当^$同时用于一个模式的时候.例:

var str1 = 'I will persist until I succeed'
var str2 ='I will'

var reg = /^I.*will$/
console.log( reg.test(str1)); // -> false
console.log( reg.test(str2)); // -> true 

我们可以看出当^$同时用于一个模式的时候, 其匹配的只是模式本身(即使字符串中含有与模式匹配的文本也不可以). 对此,我只能表示ㄟ( ▔, ▔ )ㄏ.

你是真滴皮

子表达式

子表达式是一个更大的表达式的一部分;把一个表达式划分为一系列子表达式的目的是为了把那些子表达式当做一个独立元素来使用.子表达式必须用()括起来.

我们可以来看一个例子,用正则表达式来查找IP地址.IP地址的格式是以英文句号分割的四组数字,例如12.159.46.200.我们可以把它划分为两部分,一部分是形如xxx.的模式(IP地址的前3组便是这种模式),另一个部分是xxx的模式(IP地址的最后一组数字).

var  str = 'my ip is 12.159.46.200 ok.';
var reg = /(\d{1,3}\.){3}\d{1,3}/g

console.log(str.match(reg)) // ->['12.159.46.200']

回溯引用:前后一致匹配

回溯引用指的是模式的后半部分引用在前半部分中定义的子表达式,它允许正则表达式模式引用前面的匹配结果,可将其想像成变量.

回溯引用只能用来引用模式里的子表达式(用()括起来的正则表达式片段),其匹配通常从1开始计数(\1\2,等等),在许多实现里,第0个(\0)可以用来代表整个正则表达式,同一个子表达式可以被引用任意多次。

我们来看一个例子,我们来html中的1级到6级标题标签.

var reg = /<h[1-6]>.*?<\/h[1-6]>/
var str1 = '<h1> welcome to my homeoage</h1>'
var str2 = '<h2> welcome to my homeoage</2>'
var str3 = '<h1> welcome to my homeoage</h2>'

console.log(reg.test(str1)) // -> true
console.log(reg.test(str2)) // -> true
console.log(reg.test(str3)) // -> true

我们会发现最后一个字符串并不不是我们预期的结果,但是它匹配成功了. 要解决这个问题, 就要用到我们上面所提到的回溯�引用.

var reg = /<(h[1-6])>.*?<\/\1>/
var str1 = '<h1> welcome to my homeoage</h1>'
var str2 = '<h2> welcome to my homeoage</h2>'
var str3 = '<h1> welcome to my homeoage</h2>'

console.log(reg.test(str1)) // -> true
console.log(reg.test(str2)) // -> true
console.log(reg.test(str3)) // -> false

我们可以看到,我们的模式不会匹配到第三个字符串了.

前后查找

有的时候,我们需要用正则表达式标记要匹配的文本的位置(而不仅仅是文本本身). 这样,便引出了前后查找(lookaround,对某一位置的前,后内容进行查找)的概念.

元字符 说明
?= 向前查找
?<= 向后查找
  • 向前查找

向前查找其实就是一个以?=开头的子表达式,而需要匹配的文本跟在=的后面.

例子:

var str1 = 'http://baidu.com' ;
var str2 = 'https://baidu.com' ;

// 我们想要查找文本中`:`前面的协议 .
var reg = /\w+(?=:)/;
console.log(reg.exec(str1)) // ->  http 
console.log(reg.exec(str2)) // ->  https

  • 向后查找

向后查找的操作符号是?<=,其功能与向前查找很类似.不过遗憾的是js的正则中没有向后查找.所以我只能从书上摘抄一个例子了:

文本:    
     ABC01 : $23.45
     HGG42 : $5.31

正则:
    (?<=\$)[0-9.]+

结果:
    23.45
    5.31

提示: 正则的前后查找是一种匹配但不消费的模式.

嵌入条件

正则表达式语言还有一种威力强大但不常用的功能----在表达式的内部嵌入条件处理功能.

  • 正则表达式里的条件

    正则表达式里的嵌入条件要用?来定义.并且嵌入条件不外乎有以下两种情况:

    1. 根据一个回溯引用来进行条件处理.
    2. 根据一个前后查找来进行条件处理.

    其语法结构是这样的?(条件)true-regex|false-regex.

    这个语法接受一个条件和两个将分别在这个条件得到满足和不满足时执行的子表达式.看上去与三目运算符?:很相似.

  • 回溯引用条件

    我们举个🌰(例子):

电话号码: 
     123-456-7890
     (123)-456-7890

我们要想用一个正则来匹配这个两个电话号. 这种情况下,使用嵌入回溯引用条件,便可以很便捷的写出模式.

 正则:
 
 
  (\()?\d{3}(?(1)\)|-)\d{3}-\d{4}
  
 结果:
 
     123-456-7890
     
     (123)-456-7890
     
  • 前后查找条件

前后查找条件只在一个向前查找或者向后查找操作取得成功的情况下才允许一个表达式被使.

来看一个例子:

 文本: 
   11111
   22222
   33333-
   44444.4444

 正则: 
   \d{5}(?(?=-)-\d{4})

 结果: 
  11111
  22222
  44444.4444

结论:在正则表达式模式里可以嵌入条件,只有当条件得到(或者没得到)满足时,相应的表达式才会被执行.这种条件可以是一个回溯引用(含义是检查该),也可以是一个前后查找操作.

实战演练

  • 邮箱正则

    邮箱的正则表达式是我们常用的一种, 我们先说一下邮箱的格式:

    在互联网中,电邮地址的格式是:用户名@主机名(域名)。@是英文“at”的意思,所以电子邮件地址是表示在某部主机上的一个用户账号(例:guest - at - email.xxx.xxx.net),电邮地址不是身份。---维基百科

    分析一下便知道邮箱以@为分割符号,分为用户名和主机名两部分.所以我们可以先写用户名的匹配.

    用户名的第一个字符应为字母 (a-z) 或数字,后面的字符可以有.,-,\,_这些符号,但这些符号之后必须跟着英文字母或者数字.我们来写一下用户名的正则:

    
    var reg = /^[a-z0-9]+([.-\\_]*[a-z0-9]+)*$/ 
    
    

    简单分析一下这个正则:

    1. [a-z0-9]+表示至少有一个字母或者数字,符号开头第一个字符是字母或者数字的要求.
    2. ([.-\\_]*[a-z0-9]+)*表示子表达式([.-\\_]*[a-z0-9]+)可以有零个或者多个.
    3. 分析一下子表达式([.-\\_]*[a-z0-9]+),将其分成[.-\\_]*[a-z0-9]+两部分.
    4. [.-\\_]*表示.,-,\,_可以有零个或者多个.
    5. [a-z0-9]+表示字母或者数字至少有一个.
    6. 所以([.-\\_]*[a-z0-9]+)*组合起来便符合符号之后必须跟着英文字母或者数字的要求.

    我们可以验证一下:

 var reg = /^[a-z0-9]+([.-\\_]*[a-z0-9]+)*$/ 
 var str1 = 'abc'
 var str2 = 'ab.c'
 var str3 = 'abc.'
 var str4 = '.abc'
 var str5 = 'a.b.c'
console.log(reg.test(str1)) // -> true
console.log(reg.test(str2)) // -> true
console.log(reg.test(str3)) // -> false
console.log(reg.test(str4)) // -> false
console.log(reg.test(str5)) // -> true

刚好满足要求.是不是很nice.接下来我们就该写域名的正则了.

我们来看一下域名的要求:

  • 可以包含英文字母(a-z,不区分大小写)、数字(0-9),以及半角的连接符“-”(即中横线),不能使用空格及特殊字符(如!、$、&、?等).
  • - 不能单独注册或连续使用,不能放在开头或结尾。
  • 每级域名之间用.分割.

其正则表达式如下:


 /^([a-z0-9]([-]?[a-z0-9])*.)+[a-z0-9]{2,}$/

我们来分析一下:

  1. 将正则划分成([a-z0-9]([-]?[a-z0-9])*.)+二级(或二级以上级别)域名 和[a-z0-9]{2,}顶级域名两部分.

  2. ([a-z0-9]([-]?[a-z0-9])*.)+中的的([a-z0-9]([-]?[a-z0-9])*.)类似于xxx.这样的格式,而+代表至少有一个子级别的域名,进一步分析这一部分.

  3. 其中的[a-z0-9]表示开头第一个字符只能是数字或者字母.

  4. ([-]?[a-z0-9])* 符合了-不能单独注册或连续使用,不能放在开头或结尾的要求.

  5. 最后的.则满足了域名之间用.分割的要求.

我们可以来验证一下:


var reg = /^([a-z0-9]([-]?[a-z0-9])*.)+[a-z0-9]{2,}$/
var str1 = 'baidu.com' 
var str2 = '.com' 
var str3 = 'baidu-.com' 
var str4 = 'bai--du.com' 
var str5 = 'b-a-i-d-u.com' 
var str6 = "yun.baidu.com"

console.log(reg.test(str1)) // -> true 

console.log(reg.test(str2))// -> false 

console.log(reg.test(str3))// -> false 

console.log(reg.test(str4))// -> false 

console.log(reg.test(str5))// -> true 

console.log(reg.test(str6))// -> true 

最终把它们和在一起,我们便可以得到邮箱的正则表达式:

/^[a-z0-9]+([.\-\\_]*[a-z0-9]+)*@([a-z0-9]([-]?[a-z0-9])*\.)+[a-z0-9]{2,}$/ 

用在线工具将改正则表达式其图形化.

邮箱正则

结束语

<<正则表达式必知必会>>的笔记到这里就告一段落了. 但其中内容却也只是正则表达式的冰山一角.在编程这一道路上我们还有很长的路要走,但愿你我能一直坚持下去,不求攀登到最高的顶峰,只求看那更多的风景.

后会有期
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容