一,定义
正则表达式是一种适用于字符串的模式匹配的语言。正则表达式的英语为 regular expression,常常省 略为 regex(其发音为 ['redʒeks])。
正则表达式也是一种语言,这类专为特定用途设计的语言有时称为DSL(Domain Specific Language,领域专用 语言)。正则表达式是程序设计历史上最为成功的一种DSL,其应用领域主要集中于搜索(search)与替 换(replace)。
正则表达式引擎的功能是,在收到了模式之后从目标字符串中寻找该模式。引擎的内部功能是基于 从字符串头部开始逐一对字符串进行检索比对的方式扩展而成的。为了提高执行效率,实际的引擎采取 了很多改进手段,不过,这些正则表达式引擎的内部原理对于一般的开发者来说是无需了解的。
二,相关的术语
● 模式---->>查找规则被称为模式(pattern)。
● 输入字符串 ---->>用于查找模式的对象字符串被称为输入字符串。
● 匹配---->>在输入字符串中寻找与模式相一致的字符串的过程称为匹配(match)。
三,语法
在正则表达式中,模式字符串的组成元素可以分为元字符与字面量字符两种类型。将会按照写在模 式中的内容,原封不动地解释正则表达式中的字面量字符。例如,在正则表达式中 "book" 这一字符串是 一个模式字符串,这个模式可以与以下输入字符串相匹配。
● "book"
● "books"
● "buy a book"
● "notebook"
正则表达式引擎并不会将"book" 理解为一个单词,所以自然也会与"notebook" 等字符串匹配,对此 请多加注意。
元字符 | 说明 |
---|---|
. | 任意 1 个字符 |
\s | 空白字符 |
\S | 非空白字符 |
\w | 可以构成单词的字符( A) |
\W | 不能构成单词的字符 |
\d | 数字 |
\D | 非数字 |
\b | 单词的边界 |
\B | 不是单词的边界 |
^ | 行首 |
$ | 行末 |
X? | 字符重复出现 0 次或 1 次 |
X?? | 字符 X 重复出现 0 次或 1 次(非贪心法)(B) |
X* | 字符 X 重复出现 0 次或更多次 |
X*? | 字符 X 重复出现 0 次或更多次(非贪心法) |
X+ | 字符 X 重复出现 1 次或更多次 |
X+? | 字符 X 重复出现 1 次或更多次(非贪心法) |
X{n} | 字符 X 重复出现 n 次 |
X{n}? | 字符 X 重复出现 n 次(非贪心法) |
X{n,} | 字符 X 重复出现 n 次或更多次 |
X{n,}? | 字符 X 重复出现 n 次或更多次(非贪心法) |
X{n,m} | 字符 X 重复出现至少 n 次至多 m 次 |
X{n,m}? | 字符 X 重复出现至少 n 次之多 m 次(非贪心法) |
X|Y | X 或者 Y |
[XYZ] | 1 个是 X 或者 Y 或者 Z 的字符 |
[^XYZ] | 1 个除了 X、Y、Z 以外的任意字符 |
(X) | 分组(以供之后引用) |
\数字 | 对分组的引用(C) |
(?:X) | 仅分组(D) |
X(?=Y) | 匹配 X 之后接着 Y 的情况 |
X(?!Y) | 匹配 X 之后不接着 Y 的情况 |
A 包括字母、数字、下划线以及汉字(原书中并没有提到汉字,而实际上汉字也是被包含在内的)。——译者注
B 即尽可能寻找出现次数较少的情况。——译者注
C 这里的数字是分组出现的序号。——译者注
D 即不记录分组序号,也不捕获该匹配。——译者注
特殊字符(转义字符) | 意义 |
---|---|
\n | 换行(LF) |
\t | 制表 |
\r | 回车换行(CR) |
\f | 换页 |
\V | 垂直制表 |
\cX | 控制字符。例如 \cA 为 0x01,\cB 为 0x02 等 |
\xXX | Latin-1 的编码值(X 是 0 到 9 的数字或 a 到 f 的字母) |
\uXXXX | Unicode 的编码值(X 是 0 到 9 的数字或 a 到 f 的字母) |
旗标 | 说明 |
---|---|
g | 全局匹配模式 |
i | 忽略英文字母的大小写的模式 |
m | 多行模式。^ 与 $ 将会对多行的行首与行末进行匹配 |
四,JavaScript 中的正则表达式
在 JavaScript 中,我们可以通过正则表达式对象来使用正则表达式。正则表达式对象是RegExp 类的 对象实例。下面是一个简单的使用示例。
// RegExp 的使用示例
var reg = new RegExp('^[0-9]'); // 生成一个正则表达式模式为 ^[0-9] 的 RegExp 实例
alert(reg.test('foo')); // 对输入字符串 'foo' 进行匹配
false // 结果为假
alert(reg.test('123')); // 对输入字符串 '123' 进行匹配
true // 结果为真
五, 正则表达式程序设计
test 方法 : 如果输入字符串与模式相匹配,test 方法就会返回真,如果没有得到匹配,则会返回假。
exec 方法 : exec 方法会在模式与输入字符串相匹配时返回一个结果对象(数组)。如果 没有得到匹配则返回null 值。
exec 方法的具体示例(不含全局旗标)
var text = 'abc def ghi jkl';
var reg = /(\w+)\s(\w+)/; // (\w+) 用于指定分组(共两个)
alert(reg.exec(text));
["abc def", "abc", "def"] // 数组的第 0 个元素是完整的匹配字符串。从数组的第 1 个元素起是分组引用的子字符串
exec 方法的具体示例(有全局旗标)
var text = 'abc def ghi jkl';
var reg = /(\w+)\s(\w+)/g;
alert(reg.exec(text)); // 第 1 次查找
["abc def", "abc", "def"] // 数组的第 0 个元素是完整的匹配字符串。从数组的第 1 个元素起是分组引用的子字符串
alert(reg.exec(text)); // 第 2 次查找
["ghi jkl", "ghi", "jkl"]
alert(reg.exec(text)); // 在没有找到时会返回 null
null
属性名 | 说明 |
---|---|
match(regexp) | 返回正则表达式 regexp 的匹配结果 |
replace(searchValue,replaceValue) | 将 searchValue(正则表达式或是字符串值)替换为 replaceValue(字符串或是 函数)并返回相应的字符串 |
search(regexp) | 返回正则表达式 regexp 的匹配位置的下标 |
split(separator, limit) | 通过参数 separator(字符串或是正则表达式)对字符串进行分割,并返回一个 字符串值数组 |
replace 的具体示例
var text = 'abc def ghi jkl';
// 将空格替换为逗号字符
alert(text.replace(/\s/, ',')); // 没有全局旗标
"abc,def ghi jkl"
// 对空格之前的字符进行分组,并将其移动至逗号字符之后
alert(text.replace(/(.)\s/g, ",$1"));
"ab,cde,fgh,ijkl"
// 如果使用第 2 参数,就能够对每一个匹配进行回调
// 回调函数的第 1 个参数是整个匹配,从第 2 个参数起是分组的前向引用
// 回调函数的返回值是替换字符串
// 在下面的例子中,替换操作的结果与前例相同
alert(text.replace(/(.)\s/g, function(m0,m1) { return ',' + m1; } ));
"ab,cde,fgh,ijkl"
match 的具体示例
var text = 'abc def ghi jkl';
// 设置了全局旗标
alert(text.match(/\w/g));
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]
alert(text.match(/\w+/g));
["abc", "def", "ghi", "jkl"]
alert(text.match(/(\w+)\s(\w+)/g));
[ "abc def", "ghi jkl" ] // 一个元素为所有相匹配的子字符串的数组
// 没有设置全局旗标
alert(text.match(/(\w+)\s(\w+)/));
["abc def", "abc", "def"] // 数组的第 0 个元素是整个匹配字符串
// 从数组的第 1 个元素起是分组引用的子字符串