Eagle

正则表达式

2018-09-28

正则生成

  1. new RegExp 对象的构造函数

var reg = new RegExp('^[a-z]$', 'gi')

  1. 字面量形式:

var reg = /^[a-z]$/gi

正则的组成

元字符

  1. 匹配字符

. 出来换行(\n)以外的所有字符

\w 匹配字母、数字、下划线

\W 匹配除了字母、数字、下划线

\d 匹配数字

\D 匹配除了数字以外其他字符

\s 匹配仍以的空白符(空格、\t \v \n \r \f 制表符)

\S 匹配空白符意外的任意字符

  1. 匹配位置

\b 匹配单词开始和结束的位置(\w 和 \W 之间的位置)

\B 匹配单词的非开始或者结束位置

^ 匹配行首位置

$ 匹配行尾位置

(?=p) 该位置后面字符要匹配 p

(?!p) 该位置后面字符不匹配 p

标志字符

m 多行(multi line)

g 全局(global)

i 不区分大小写(ignore)

例如:

1
2
3
4
5
var reg = /^abc/;
var str = 'test\nabc'; // 匹配不上,因为 \n 是换行,不能匹配多行

var reg = /^abc/m;
var str = 'test\nabc'; // 匹配上

限定符

* 匹配 0 次以上

+ 匹配 1 次以上

? 0 次或 1 次

{m} 匹配 m 次

{ m, } 至少匹配 m 次

{m, n} 至少 m 次,最多 n 次

转义字符

*+?|\/{}[]()^$ 需要 \ 进行转义

正则方法

正则实例

  1. test()
    参数为 string,返回值为 boolean

例如:

1
/javascript/.test("dadjavascript");  //  true

  1. exec()

参数string,返回 [] ,存放匹配结果,如果没有匹配上返回 null

例如:

1
2
3
4
5
6
7
var string = "a and b and c";
var reg = /(a and)?(b and)?c/;

reg.exec(string);

结果:
["a and b and c", "a and ", "b and "]

返回值忠包含另外两个属性:index 和 input

index 表示匹配项在字符串中的位置。(上面代码匹配项为 short ,对应的位置 是16);

input 表示应用正则表达式的字符串

  1. lastIndex

匹配的位置,可读可写

注意:
重复执行 test() ,他会记住匹配的位置,从上一次匹配的位置继续匹配

  1. 不具有标志 g 和不表示全局模式的正则对象不能使用 lastIndex 属性

    1
    2
    3
    4
    5
    6
    7
    var reg = /abc/;
    var str = '1#abc+abc';
    console.log(rgb.test(str)); //true
    console.log(rgb.lastIndex); // 0
    console.log(rgb.test(str)); // true
    console.log(rgb.lastIndex); // 0
    console.log(rgb.test(str)); // true
  2. lastIndex 用于规定下次匹配的起始位置

1
2
3
4
5
6
7
8
var reg = /abc/g;
var str = '1#abc+abc';
var str2 = '2abc';
console.log(rgb.test(str)); //true
console.log(rgb.lastIndex); // 5
console.log(rgb.test(str)); // true
console.log(rgb.lastIndex); // 9
console.log(rgb.test(str2)); // false 最后没有了,所以匹配不上了
  1. 如果再成功匹配字符串之后,想要重新匹配新的字符串,需要将该属性设置成 0
    1
    2
    3
    4
    5
    6
    7
    var reg = /abc/g; 
    var str = '1#abc+abc';
    var str2 = '2#abc';
    console.log(reg.test(str)); // true
    console.log(reg.lastIndex); // 5
    console.log(reg.test(str2)); // false
    console.log(reg.lastIndex); // 0

字符串实例

search()
参数:需要检索的字串 / 正则对象

返回值:-1 / 字符串忠 第一个预正则相匹配的字串的位置

  1. 不执行全局匹配,忽略 g
  2. 不能使用 lastIndex
  3. 总是从字符串开始进行检索
1
2
3
'hello,javascript'.search('javascript');              //6     
'hello,javascript'.search(/javascript/); //6
'hello,javascript,javascript'.search(/javascript/g); //6

match()

参数:需要检索的字串 / 正则对象

返回值: array / null

  1. 如果正则没有 g ,字符串只会匹配一次
  2. 如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到被检索字符串中的所有匹配的子串,它 的数组元素中存放的是被检索字符串中所有的匹配的子串,而且也没有 index 属性或 input 属性;
1
2
'hello,javascript'.match('javascript');
'hello,javascript'.match(/javascript/);


replace()

替换

参数:

  1. 被替换的文本(字符串/正则)
  2. 替换成的文本(字符串/函数),如果是字符串,可以用特殊变量来代替

返回值:替换后的字符串

例如:

1
2
3
4
5
6
7
8
9
10
11
'hello, javascript'.replace(' javascript', 'nodejs');
'hello,javascript'.replace(/javascript/, 'nodeJs');
'javascript nodejs'.replace(/(\w+)\s(\w+)/, "$2 $1")
'javascript nodejs'.replace(/(\w+)\s(\w+)/, function( match, p1, p2, offset, string ){
// match: 匹配的字串
// p1, p2... 对应 $1 $2
// offset 匹配的字符串忠的偏移量
// string: 被匹配的字符串
console.log(match, '---', p1, p2, offset, string);
return [p1, p2].join('-')
})

$$ 插入 $

$& 插入匹配的字串

$“ 插入匹配的左侧

$” 插入撇右侧

split()

切割

  1. 用捕获括号的时候会将匹配结果也包含在返回的数组中。
1
'hello,javascript'.split(/(,)/);  //["hello", ",", "javascript”]

正则匹配

  1. 精确匹配:/hello/.test(‘hello’)
  2. 模糊匹配:
  3. 排除字符 ^
  4. 分支匹配 | (惰性)
  5. 分组匹配 ()
  6. 分组引用 $1 $2
  7. 反向引用 \1 \2
    (正则本身引用分组,但只能引用之前出现的分组)
    1. 括号以左开括号为准
    2. 引用不存在的分组,正则不会报错,只是匹配反向引用的字符串本身
    3. 反向分组后面量词的话,反向分组最终捕获到数据是最后一粒匹配: const reg = /(\d)+ \1/; ‘12345 1’.match(reg)
  8. 位置匹配
  9. 贪婪模式(默认)
  10. 非贪婪模式
    再限定符后面加 ?
  11. 捕获分组 ()
  12. 非捕获分组 (?:)

常用的正则

  1. 匹配汉字:^[\u4e00-\u9fa5]{0,}$
  2. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
  3. 日期格式:^\d{4}-\d{1,2}-\d{1,2}
  4. 时间:/^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/
  5. 一年的12个月 (01~09和1~12):^(0?[1-9]|1[0-2])$
  6. 一个月的31天 (01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
  7. 中国邮政编码:[1-9]\d{5}(?!\d)
  8. IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
  9. 匹配id: '<div id="container" class="main"></div>’.match(/id="[^"]*"/ );
  10. 格式化货币:function format (num) { return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/, ",").replace(/^/, "$$ "); };
  11. 去掉左右空格: ' javascript '.replace(/^\s+|\s+$/g, '');
  12. 每个单词的首字母转换为大写 : function format(str) { return str.toLowerCase().replace(/(?:^|\s)\w/g, function (c) { return c.toUpperCase(); }); }
  13. 匹配标签: "aaa<title>hello</title>" .match(/<([^>]+)>[\d\D]*<\/\1>/)
  14. 身份证号码:/^(\d{15}|\d{17}[\dxX])$/

正则的回溯

1
'"abc"de'.match(/".*"/)

正则效率

  1. 使用确定的字符直接匹配
  2. 使用非捕获分组(省内存)
  3. 减少分支数量,缩减范围:/red|read/ 改为 /rea?d/
  4. 正则效率和正则可读性需要做一个取舍
Tags: js