浅谈JavaScript中的正则表达式

引言

  对于正则表达式我想作为程序员肯定使用过它,那天书般的表达方式,我用一次就记住它了。这篇博客先介绍一些正则表达式的内容,然后介绍JavaScript中对正则表达式特有的改进。下面开始介绍正则表达式吧。

正则表达式是什么?

  相信大家一定使用过windows的资源管理器搜索功能。例如我需要找出全部的txt文档,我们通常都会使用*.txt去进行匹配。在这里,*会被解释成任意的字符串。和通配符类�BC�,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精 确地描述你的需求——当然,代价就是更复杂

入门

  假设我们现在需要匹配一个形式是这样的字符串(电话号码):025-85862979。在正则表达式中\d表示的是0-9任意的一个数字,那么使用最简单的方法我们可以使用下面这种正则表达式来进行匹配\d\d\d-\d\d\d\d\d\d\d\d。这种最简单的方法就是将每一个数字分割为\d进行表示。其实我们可以使用更加简洁的方式来表达。例如:0\d{2}-\d{8}。这里{2},{8}表示前面重复的次数。到此为止,\d是我们介绍的第一个元字符,下面我们将介绍更多元字符。

元字符

  我们先来看一个例子:\ba\w*\b这个正则表达式匹配上面呢?它匹配以a开头的单词。先是某个单词开始处(\b),然后是字 母a,然后是任意数量的字母或数字(\w*), 最后是单词结束处(\b)。\d+匹配1个或更多连续的数字。 这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次。\b\w{6}\b 匹配刚好6个字符的单词。

  常见的元字符如下:

代码说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

 

  通过这个表格,我们看到正则表达式中常用的一些元字符的含义。对于^和$来说,有一点特别要注意:如果不使用^和$的话,对于\d{5,12}而言,使用这样的方法就只能保证字符串里包含5到 12连续位数字,而不是整个字符串就是5到12位数字。

字符转义

  如果你想查找元字符本身的话,比如你查找.,或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。当然,要查找\本身,你也得用\\.

  例如:deerchao\.net匹配deerchao.net,C:\\Windows匹配C:\Windows。

重复

  你已经看过了前面的*,+,{2},{5,12}这几个匹配重复的方式了。下面是 正则表达式中所有的限定符(指定数量的代码,例如*,{5,12}等):

代码/语法说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

 

  下面是一些使用重复的例子:

  Windows\d+匹配Windows 后面跟1个或更多数字

  ^\w+匹配一行的第一个单词(或整个字 符串的第一个单词,具体匹配哪个意思得看选项设置)

字符类

  要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元 音字母a,e,i,o,u),应该怎么办?

  很简单,你只需要在方括号里列出它们就行了,像[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(.或?或!)。

  我们也可以轻松地指定一个字符范围,像[0-9]代 表的含意与\d就是完全一致的:一位数字; 同理[a-z0-9A-Z_]也完全等同于\w(如 果只考虑英文的话)。

  下面是一个更复杂的表达式:\(?0\d{2}[) -]?\d{8}。

  “(”和“)”也是元字符,所以在这里需要使用转义。下面我们详细的解释下这段正则表达式。

  这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455, 或02912345678等。我们对它进行一些分析吧:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中 的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

 分支条件  

  不幸的是,刚才那个表达式也能匹配010)12345678或(022-87654321这样的“不正确”的格式。要解决这个问题,我们需要用到分枝条件。正则表达式里的分枝条件指的是有几种规则,如 果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看 例子:

  0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号 (0376-2233445)。

  \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}这 个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间 隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。

  \d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编 的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。 如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮 编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

分组(捕获性分组)

  我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达 式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。

  (\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹 配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重 复3次,最后再加上一个一到三位的数字(\d{1,3})。

  下面我们来看一下常用的分组语法:

分类代码/语法说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成 (?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置

  在这里面,我会重点讲一下非捕获性分组。我们还是举个例子来看。前面的例子(\d{1,3}\.){3}会匹配一个三位数字加上一个英文句号。使用捕获性分组时,任何匹配这个分组的字符将会被捕获。这些符合条件的字符会被存储在内存中,以便下一次使用。其实,很多时候我们只是进行简单的匹配工作。默认的方式就造成了内存的浪费。因此,使用非捕获性分组,我们可以避免无谓的内存消耗。(?:\d{1,3}\.){3}。非捕获性分组和匹配无关,只是提升效率。

反义

  有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义:

 
代码/语法说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

 

  例子:\S+匹配不包含空白符的字符串。<a[^>]+>匹配用 尖括号括起来的以a开头的字符串。 

JavaScript中的正则表达式

  在JavaScript中使用RegExp来进行正则匹配。在JS中有两种方法来构建一个RegExp对象。通常优先的方法是使用正则表达式字面量,正则表达式字面量被包含在一对斜杠中。在JS中有3个标记可以在RegExp中设置,它们分别是字母g、i、m,它们可以直接添加到RegExp字面量的末尾。下面我们通过一个例子来看一下。

var regexp = /0\d{2}-\d{8}|0\d{3}-\d{7}/g;

  下面我们来看一下g、i、m三个字母在JS正则表达式中的含义。如图:

  创建一个正则表达式另一种方法是使用RegExp构造器。这个构造器接收一个字符串,并把它编译成一个RegExp对象。创建这个字符串要小心,因为反斜杠在正则表达式和在字符串字面量中有一些不同的含义。通常需要双写反斜杠及对引号进行转义。第二个参数是一个指定标记的字符串(g、i、m)。

参考文献

  http://www.oschina.net/question/12_9507

  https://msdn.microsoft.com/zh-cn/library/az24scfc.aspx

posted @ 2015-12-22 16:53  dreamGong  阅读(234)  评论(0编辑  收藏  举报