正则表达式

对字符串的处理,一般分为字符串操作和正则操作。

字符串操作
  • str.search(regStr) 返回 regStr 在 str 中第一个出现的位置
  • str.replace(regStr,newStr) 返回替换在 str 中 regStr 后字符串
  • str.substring(n1,n2) 返回 str 从 n1 位置到 n2 位置前一个字符串
  • str.chartAt(n) 返回 n 位置字符
  • str.split(regStr) 返回以 regStr 隔开的数组
  • str.match(reg) 返回在 str 中符合正则 reg 的字符串数组
正则操作

var reg=new RegExp(regStr,’i’); //创建正则对象

var reg=/regStr/i; //隐式创建正则对象

  • reg.test(str) str 是否包含 reg 返回 true/false
  • reg.exec(str) 返回匹配到的字符串和最后一次的匹配字符串最后位置的下一个索引

基础用法

  1. /a|b/ a 或 b
  2. /[abc]/ a 或 b 或 c
  3. /[a-zA-Z0-9]/ 所有数字和字母
  4. /[^a-za-z0-9]/ 除了数字和字母
  5. /.+/ 任意字符
  6. /\d/ 等价于/[0-9]/ 数字
  7. /\w/ 等价于/[a-z0-9_]/ 数字、字母和下划线
  8. /\s/ 等价于/“ “/ 空格
  9. /\D/ 等价于/[^0-9]/ 非数字
  10. /\W/ 等价于/[^a-z0-9_]/ 除了数字、字母和划线
  11. /\S/ 等价于/[^” “]/ 除了空格
  12. /\d{n,m}/ 数字最少出现 n 次,最多出现 m 次
  13. /\d{1,}/ 等价于/\d+/ 数字最少出现 1 次
  14. /\d{0,}/ 等价于/\d*/ 数字最少出现 0 次
  15. /\d{0,1}/ 等价于/\d?/ 数字最多出现 1 次
  16. /^\d$/ 以数字开头且以数字结尾
  17. /[\u4e00-\u9fa5]/ 汉字匹配范围
  18. \b 单词边界
  19. \B 非单词边界
  20. ?=n 匹配任何其后紧接指定字符串 n 的字符串
  21. ?!n 匹配任何其后没有紧接指定字符串 n 的字符串

疑难点

在个人接触正则过程中遇到的一些不易理解的地方

用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。

表达式 描述
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (\ ) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y\ ies) 就是一个比 ‘industry\ industries’ 更简略的表达式。
(?=pattern 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,’Windows (?=95\ 98\ NT\ 2000)’ 能匹配 “Windows 2000” 中的 “Windows” ,但不能匹配 “Windows 3.1” 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如’Windows (?!95\ 98\ NT\ 2000)’ 能匹配 “Windows 3.1” 中的 “Windows”,但不能匹配 “Windows 2000” 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

一直对正则中的 match 和 exec 不易分清,下面来做一下比较。

1. match

match 方法属于 String 正则表达方法

语法:

1
str.match(regexp)

str:要进行匹配的字符串

regexp:一个正则表达式(或者由 RegExp()构造成的正则表达式)

match 的用法主要区分就是正则表达式是否有全局标示 g

  1. 如果有 g 全局标志,那么返回的数组保存的是,所有匹配的内容。

  2. 如果没有 g 全局标志,那么返回的数组 arr.arr[0]保存的是完整的匹配.arr[1]保存的是第一个括号里捕获的字串,依此类推 arr[n]保存的是第 n 个括号捕获的内容。

2. exec

与 match 方法不同 exec 属于正则表达式的方法

语法:

1
var result1 = regexp.exec(str);

regexp:正则表达式

str:要匹配的字串

exec 与 match 的关联就是 exec(g 有没有都无影响)就等价于不含有 g 全局标志的 match,即返回数组 arr[0]为匹配的完整串,其余的为括号里捕获的字符串。

但如果有 g 对 exec 本身的影响是,当一个具有 g 的正则表达式调用 exec()时,他将该对象的 lastIndex 设置到紧接这匹配子串的字符位置。当第二次调用 exec 时将从
lastIndex 所指示的字符位置开始检索,利用这个特点可以反复调用 exec 遍历所有匹配,等价于 match 具有 g 标志。

1
2
3
4
var arrmatch = str.match(reg)
for (var i = 0; i < arrmatch.length; i++) {
document.write(arrmatch[i] + '---->')
}

可见上面的 exec 和 match 是等价的.

reg.exec(str) 返回匹配到的字符串和最后一次的匹配字符串最后位置的下一个索引如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var str = 'abc123bef345olj89,ed'
var reg = /\d+/g

console.log(reg.exec(str))
console.log(reg.lastIndex)

console.log(reg.exec(str))
console.log(reg.lastIndex)

console.log(reg.exec(str))
console.log(reg.lastIndex)

console.log(reg.exec(str))
console.log(reg.lastIndex)

结果

image

1
2
3
4
5
6
7
var str = 'abc123bef345olj89,ed'
var reg = /\d+/g
var match = null
while ((match = reg.exec(str)) !== null) {
console.log(match)
console.log(reg.lastIndex)
}

总结

  • 主要区分 match 具有 g 和没有 g 的区别,没有 g 的时候与 exec 是等价的。

  • 而 exec 返回的串类型不受 g 影响,但具有 g 时候会驱动 lastIndex 可以模拟遍历所有匹配,可以与 match 具有 g 的时候等价。

顺便加强理解

  1. ip 正则表达式
    格式由”.”分割成四段,每一段范围是 0-255,拿出其中一段进行分析
范围 表达式
0-9 \d
10-99 [1-9]\d
100-199 1\d{2}
200-249 2[0-4]\d
250-255 25[0-5]

所以,其中一段构成的正则表达式是

1
\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]


整个 ip 正则为

1
/^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
  1. 同理端口号范围是 0-65535
范围 表达式
0-9 \d
10-99 [1-9]\d
100-999 [1-9]\d{2}
1000-9999 [1-9]\d{3}
10000-59999 [1-5]\d{4}
60000-64999 6[0-4]\d{3}
65000-65499 65[0-4]\d{2}
65500-65529 655[0-2]\d
65530-65535 65553[0-5]

所以,整个端口号正则为

1
;/\d|[1-9]\d{1,3}|[1-5]d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|65553[0-5]/

参考菜鸟教程正则教程