Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

正则表达式要点 #31

Open
weekeight opened this issue Oct 12, 2015 · 1 comment
Open

正则表达式要点 #31

weekeight opened this issue Oct 12, 2015 · 1 comment

Comments

@weekeight
Copy link
Owner

正则表达式要点

写在前面

正则表达式相信大家都很熟悉了,但是很多时候需要写或看到一些稍微复杂的正则时就往往感到那都是“似曾相识”。这篇文章没什么干货,但都是正则里的要点,如果你此时此刻感觉正则只是那样的“似曾相识”,那不妨扫两眼来增强你的记忆,唤起正则的小宇宙吧。

基本方法

RegExp对象的方法

  1. test
  2. exec
    • 如果找到匹配的文本返回一个结果数组,否则返回null
    • 结果数组的第0个元素是与正则表达式匹配的文本,第1个元素是正则表达式第1个子表达式相匹配的文本,一次类推;结果数组有两个特殊属性,index属性表示匹配文本的第一个字符的位置。input属性表示被检索的字符串
    • 当正则表达式regSample是全局匹配g时,它会在regSample.lastIndex属性指定的字符处开始检索字符串,在匹配后,它将把regSample.lastIndex属性设置为匹配文本的最后一个字符的下一个位置并终止匹配搜索。故可以通过反复调用exec方法来遍历整个字符串,直到找不到匹配则返回null,并将lastIndex属性重置为0
var str = 'hello, I am weekeight'
var regSample1 = /\b(\w+)\b/
var regSample2 = /\b(\w+)\b/g     //有全局标志

var result1 = regSample1.exec(str);  //["hello", "hello"]  result1.index == 0 
var result2 = regSample2.exec(str);  //["hello", "hello"]  result1.index == 0 regSample2.lastIndex === 5

String字符串的方法

  1. match
    • 当正则不是全局匹配时,返回结果和exec方法一致
    • 当正则是全局匹配时,则在字符串里全局检索,找到所有匹配子字符串,不提供任何关于正则子表达式的信息也没有index和input属性
  2. serch
  3. replace
  4. split

简单模式

元字符

( )  [  ]  \  ^  $  |  ?  *  +  . 

字符类

  1. 简单类
    • [abc]
  2. 负向类
    • [^abc]
  3. 范围类
    • [a-z]
  4. 组合类
    • [a-z0-9]
  5. 预定义类
    • . 除了换行符和回车之外的任意字符
    • \d 数字
    • \D 非数字字符
    • \s 空白字符
    • \S 非空白字符
    • \w 单词字符 等同于 [a-zA-Z_0-9]
    • \W 非单词字符

注: \b\B不是已定义的字符类,而是字符边界标识

量词

简单量词

代码 描述
? 出现零次或一次
* 零次或多次
+ 一次或多次
{n} n次
{n,m} 至少出现n次但不超过m次
{n,} 至少出现n次

贪婪、惰性和支配量词

贪婪 惰性 支配 描述
? ?? ?+ 零次或一次
* *? *+ 零次或多次
+ +? ++ 一次或多次
{n} {n}? {n}+ n次
{n,m} {n,m}? {n,m}+ n到m次
{n,} {n,}? {n,}+ 至少n次
  1. 贪婪量词,理解为只要能匹配上就尽量多重复,尽量让这个量词表达最大次数的含义。它会先尽量去匹配整个字符串,如果最大的字符串没匹配再回溯。以('a "witch" and her "broom" is one').match(/".*"/)大概的匹配过程如下:
    • 从字符串位置0开始找到匹配正则表达式的第一个字符",在位置3
    • 然后由于*是贪婪量词,故会尽量重复匹配元字符.,一直搜索到字符串结尾处。过程中即使遇到匹配上的也不停止,一定要先搜索到字符串结尾
    • 回溯匹配正则表达式的最后一个"
    • 直到回溯到broom""则匹配上了,所以最后结果是 "witch" and her "broom"
  2. 惰性量词,理解为只要能匹配上就尽量少重复。以('a "witch" and her "broom" is one').match(/".*?"/)大概的匹配过程如下:
    • 从字符串位置0开始找到匹配正则表达式的第一个字符",在位置3
    • 由于*?是惰性量词,表示0个或多次,那么它会很懒惰地尝试表示0次的时候是否能匹配
    • *? 表示0次时,下一个要匹配的就是正则里最后的那个",但是发现字符串第4个位置不匹配,这时候惰性量词*?再尝试表示1次,一直尝试直到匹配到了 "witch"
  3. 支配量词表示尝试一次整个字符串匹配,如果不匹配则终止。浏览器对支配量词的支持不完善,慎用

注: 关于贪婪与惰性的匹配搜索过程建议看这篇文章,非常详细Greedy and Lazy

复杂模式

简单分组(不展开描述)

反向引用

  1. 当通过.test()方法调用时,记录在RegExp.$中,如
var str = 'hello weekeight';
var reg = /week(eight)/
reg.test(str)
console.log(RegExp.$1) //eight
  1. 直接在表达式里使用,通过\加上相应数字来表示第几个分组
var str = 'hello weekeighteight';
var reg = /week(eight)\1/
reg.test(str)  //true
  1. String对象的replace方法里使用,通过$加上对应数字来表示第几个分组
var str = 'hello weekeight';
var reg = /week(eight)/
str.replace(reg, '$1') //hello eight

候选(|不展开描述)

非捕获性分组

创建反向引用的分组称为“捕获性分组”,但在复杂的正则表达式中这样会降低匹配效率,当不需要反向引用分组的时候可以考虑使用“非捕获性分组”来降低存储结果的开销,同时也拥有匹配字符串的能力。在分组的左括号后面加上?:则表达这个分组是“非捕获性”的,不会创建反向引用。

var str = 'hello weekeight';
var reg = /week(?:eight)/
reg.test(str)
console.log(RegExp.$1) //undefined

String对象的match方法使用,捕获性分组会把信息存到返回的结果数组中,而非捕获性分组则不会

var str = 'hello , I am weekeight';
var reg1 = /week(eight)/;
var reg2 = /week(?:eight)/;

str.match(reg1);  //["weekeight", "eight"]
str.match(reg2); //["weekeight"]

前瞻

  1. 正向前瞻 : 接下来出现的应该是某特定字符串集 (?=)
  2. 负向前瞻 : 接下来的不应该出现的特定字符串集 (?!)

注: 虽然前瞻需要用到括号(),但是这不是一个分组,不会创建反向引用

var str1 = 'hello, I am weekeight';
var str2 = 'hello,I am weekweek';
var reg1 = /week(?=eight)/
var reg2 = /week(?!eight)/

console.log(reg1.test(str1));  //true
console.log(reg2.test(str1));  //false
console.log(reg2.test(str2));  //true

边界

边界 描述
^ 行开头
$ 行结尾
\b 单词的边界
\B 非单词的边界
var str = 'hello, I am weekeight';
var reg = /\b(\w+?)\b/g
str.match(reg);   //["hello", "I", "am", "weekeight"]  注意匹配结果中`hello`是没有逗号`,`的

最后

最后,在我们查看别人写的或者自己以前写的比较复杂的正则表达式的时候少不了用一些可视化工具来分析理解,Regulex 就是一个很不错的可视化工具。

@DennisLi87
Copy link

Regulex 这个网站不错!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants