Extreme Thinking
正则表达式

2015-04-20


本文介绍js里的正则表达式用法, 多数知识也适用于其他语言下的正则表达式. 下面是几个有用的资源:

正则表达式引擎

linux, php, perl, python, java, C++, .net等各种语言都支持正则表达式,需要注意的是许多引擎很类似,但不完全一样,支持的正则表达式语法可能有细微的差别。

有两种类型的引擎:文本导向(text-directed)的引擎和正则导向(regex-directed)的引擎。一些非常有用的特性,如“惰性”量词(lazy quantifiers)和反向引用(backreferences),只能在正则导向的引擎中实现,因此正则导向的引擎是目前最流行的引擎。

你可以轻易分辨出所使用的引擎是文本导向还是正则导向。如果反向引用或“惰性”量词被实现,则可以肯定你使用的引擎是正则导向的。你可以作如下测试:将正则表达式regex|regex not应用到字符串“regex not”, 如果匹配的结果是regex, 则引擎是正则导向的, 如果结果是regex not,则是文本导向的。因为正则导向的引擎是“猴急”的,它会很急切的进行表功,报告它找到的第一个匹配。正则导向的引擎总是返回最左边的匹配, 即使以后有可能发现一个“更好”的匹配,正则导向的引擎也总是返回最左边的匹配

JS里使用正则表达式的方法

正则表达式可以被用于:

  • RegExp的方法:
    • test() - 检索字符串中的指定值。返回值是布尔值。
    • exec() - 返回一个数组,数组中的第一个条目是第一个匹配,其他的是反向引用
  • String对象中的正则表达式方法:
    • match(pattern) - 返回 pattern 中的子串或 null
    • replace(pattern, replacement) - 用 replacement 替换 pattern
    • search(pattern) - 返回字符串中 pattern 开始位置
    • split(pattern) - 返回字符串按指定 pattern 拆分的数组

创建正则表达式:

有两种方法创建正则表达式:

var re = /ab+c/i;                 //方法1: 字面量
var re = new RegExp("ab+c", "i"); //方法2: RegExp构造函数, 当"ab+c"是一个变量时, 这个方法比较有用

正则表达式格式为/pattern/flags, flags可以为"i", "g", "m":

  • i - 正则表达式默认是大小写敏感的, 使用"i"表示不区分大小写
  • g - 全局匹配,默认行为是匹配第一个时返回
  • m - 多行匹配

字符含义

有12个字符被保留作特殊用途,这些特殊字符也被称作元字符。他们是: [ ] \ ^ $ . | ? * + ( ) 如果需要匹配这些元字符,需要用 \ 转义.

元字符 描述
[ ] 表示字符集
^ 用在字符集里紧跟"["表示对字符集取反,另一个用法是表示匹配第一个字符
? * + 表示重复, ?表示重复0次或1次, *表示重复0次或多次, +表示重复1次或多次
. 表示任意字符,等于是字符集[^\n\r](Window)或[^\n]( Unix)的简写
^ $ ^表示匹配第一个字符, $表示匹配最后一个字符. ^a将会匹配字符串“abc”中的a,^b将不会匹配“abc”中的任何字符,c$匹配“abc”中的c
| 表示或
( ) 表示字符组, 圆括号里的匹配会形成分组, $1表示第1个分组, $2表示第2个分组, match()方法会返回分组数组

下面是特定含义的字符:

  • 不可见字符:
    • \t 代表Tab(0x09)
    • \r 代表回车符(0x0D)
    • \n 代表换行符(0x0A), 要注意的是Windows中文本文件使用“\r\n”来结束一行而Unix使用“\n”
    • \f 代表换页符
    • \v 代表垂直制表符
  • 字符集简写:
    • \d 代表数字,与[0-9]等效
    • \w 代表单词字符,与[A-Za-z0-9_]等效
    • \s 代表空白字符,与[\f\n\r\t\v]等效
    • \D 表示取反\d, [\D] = [^\d]
    • \W 表示取反\w, [\W] = [^\w]
    • \S 表示取反\s, [\S] = [^\s]
    • \xhh 表示ascii码0xhh对应的字符, 譬如\x21表示ascii字符0x21, 即字符"!"
    • \uhhhh 表示unicode码0xhhhh对应的字符
  • 单词边界:
    • \b 表示单词边界,\bis\b将匹配字符串“This island is beautiful”里的单独的is,不会匹配This和island里的is
    • \B 表示非单词边界,er\B能匹配“verb”中的“er”,但不能匹配“never”中的“er”
  • 字符串开始与结束:
    • \A 表示字符串开头,类似^
    • \Z 表示字符串结尾,类似$

示例

例1: 基本用法

var str = "Hello China, Welcome to China";
var str1 = str.replace(/China/, "Japan"); //"Hello Japan, Welcome to China"
var str2 = str.replace(/China/g, "Japan"); //Hello Japan, Welcome to Japan
var pattern = /china/i;         //不区分大小写
var bFound = pattern.test(str); //true

例2: 利用\xhh匹配ascii字符

//remove a=xxx:100 lines from SDP
newSDP = oldSDP.replace(/a=[A-Za-z0-9_-]+:100[\x20-\x7e]*\r\n/g,"");

例3: 利用()分组和$1将"Doe, John"转换为"John Doe"

var name = "Doe, John";
name = name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1");

例4: 利用function把字符串中所有单词的首字母都转换为大写

name = 'aaa bbb ccc';
name = name.replace(/\b\w+\b/g, function(word){
  return word.substring(0,1).toUpperCase()+word.substring(1);}
  );