10分钟快速掌握正则表达式

一、背景

        因为工作的时候要做一些表单校验和精准搜索。所以写下这篇文章。

        当涉及到正则表达式的理解和使用时,尽管它们提供了强大的文本处理能力,但其语法的复杂性常常让人倍感挑战。即使是对经常使用正则表达式的专业开发者来说,也常常会因为语法细节和复杂性而感到困扰。这种挑战性不仅体现在编写正则表达式的过程中,还体现在对已有表达式的阅读和理解上。为了克服这些困难,我们有必要对正则表达式的语法和用法进行系统的学习和总结,以便在需要时能够快速准确地使用它们。因此,本文旨在提供一个关于正则表达式的详细指南,以便读者在将来能够方便地回顾和参考。

        测试工具地址:regex101: build, test, and debug regex

二、什么是正则表达式

        正则表达式是由一些具有特殊含义的字符组成的字符串,多用于查找、替换符合规则的字符串。

三、元字符

      即为有特定含义的字符,常见的元字符如下:

        正则表达式元字符是那些在正则表达式中具有特殊意义的专用字符,它们可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。以下是一些常用的正则表达式元字符的举例:

  1. .(点号)
    • 匹配除换行符之外的任何单个字符。例如,在字符串“abc\ndef”中,. 可以匹配“a”、“b”、“c”、“d”和“e”,但不能匹配换行符\n
  2. *(星号)
    • 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"*。 等价于 {0,}
  3. +(加号)
    • 匹配前面的子表达式一次或多次。例如,zo+ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}
  4. ?(问号)
    • 匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do" 或 "does" 中的 "do" 和 "does"。? 等价于 {0,1}
  5. {n}
    • n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o。
  6. {n,}
    • n 是一个非负整数。至少匹配 n 次。例如,o{2,} 不能匹配 "Bob" 中的 "o",但能匹配 "foooood" 中的所有 o。"o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*"。
  7. {n,m}
    • m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o。"o{0,1}" 等价于 "o?"。
  8. ^(脱字符)
    • 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
  9. $(美元符号)
    • 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
  10. \b(退格符)
    • 匹配一个单词边界,即字与空格间的位置。例如,\bhi\b 匹配 "hello hi world" 中的 "hi",但不会匹配 "hiking"。
  11. \B(非单词边界)
    • 匹配非单词边界。\Bhi 匹配 "hiking" 中的 "hi",但不会匹配 "hello hi world" 中的 "hi"。
  12. [...](字符集)
    • 匹配方括号中的任何字符。例如,[abc] 匹配 "a"、"b" 或 "c"。你也可以使用范围,如 [a-z] 匹配任何小写字母。
  13. [^...](否定字符集)
    • 匹配任何不在方括号中的字符。例如,[^abc] 匹配除了 "a"、"b" 或 "c" 之外的任何字符。
  14. \d
    • 匹配一个数字字符。等价于 [0-9]。
  15. \D
    • 匹配一个非数字字符。等价于 [^0-9]。
  16. \s
    • 匹配任何空白字符,包括空格、制表符、换页符等。等价于 [\f\n\r\t\v]。
  17. \S
    • 匹配任何非空白字符。等价于 [^\f\n\r\t\v]。
  18. \w
    • 匹配任何字类字符,包括下划线。等价于 [a-zA-Z0-9_]。
  19. \W
    • 匹配任何非字类字符。等价于 [^a-zA-Z0-9_]。

四、字符转义

有的时候需要用到元符号本身的话,就需要用到转义。比如:

        1. 查找.*符号是就会出现问题。这个时候我们就要用到\来取消这些字符的特殊意义

此时你就应该使用\.\*,当然啦。你要哪个用\本身就使用\\

例如:

        \bwww\.cdy\.cn匹配www.cdy.cn

        C:\\Windows匹配C:\Windows。

五、限定符

        限定字符多用于重复匹配次数,常用的限定字符如下:

        详解和实例:

 a*结果如下图:

 a+结果如下图:

 a?结果如下图:

 a{6}结果如下图:

 a{2,6}结果如下图:

 a{2,}结果如下图:

六、字符类

        你想匹配没有预定义元字符的字符集合(比如字母c,d,y),应该怎么办?很简单,你只需要在方括号里列出它们就行了。

[cdy]就可以匹配任意一个括号内的字母了,下图:

[.?!]就可以匹配任意一个括号内的标点符号了,下图:

        我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

如下表达式:\(?0\d{2}[) =-]?\d{8}

        首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格、=中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。结果如下图:

七、分枝条件

         正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。

        0\d{2}-\d{8}|0\d{3}-\d{7}:这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号,一种是4位区号,7位本地号。如下图所示:

        \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}:这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。

 八、分组

        字符分组多用于将多个字符重复,主要通过使用小括号()来进行分组

例如:([0-9]\w){3}

        会匹配第一个为任意数字,第二个为任意字母或数字或下划线或汉字的两位数重复三次;

 

        小括号的另一种用途是通过语法(?#comment)来包含注释

        例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。

        要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。例如,我们可以前面的一个表达式写成这样。

九、反义

        正则表达式中的反义(Negation)通常用于匹配不属于某个字符类或满足某个条件的字符。以下是一些使用反义的正则表达式示例:

1.匹配非数字字符:

使用 \D 来匹配任何非数字字符。例如,\D+ 匹配一个或多个非数字字符。

示例:Hello123 中,Hello 会被 \D+ 匹配。
2. 匹配非空白字符:

使用 \S 来匹配任何非空白字符。空白字符包括空格、制表符、换页符等。

示例:Hello World 中,Hello 和 World 会被 \S+ 匹配(假设中间有两个空格)。
3. 匹配非单词字符:

使用 \W 来匹配任何不是字母、数字、下划线或汉字的字符。

示例:Hello_World! 中,_ 和 ! 会被 \W 匹配。
4. 匹配非单词边界:

使用 \B 来匹配不是单词开头或结束的位置。

示例:在 Hello-World 中,- 两侧的位置都是 \B 的匹配对象,因为它不是单词的开头或结束。
5. 匹配除了指定字符以外的字符

使用 [^...] 来匹配除了方括号内字符以外的任何字符。

示例:[^aeiou] 匹配除了 aeiou 以外的任何字符。
6. 排除某个模式

使用 (?!...) (如果支持)来排除某个模式。这是一个否定的前瞻断言,表示后面不能跟着某个模式。

示例:(?!abc)\w+ 匹配不以 abc 开头的单词。

十、懒惰匹配和贪婪匹配

        当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

        有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

 (?<=    # 断言要匹配的文本的前缀
      <(\w+)> # 查找尖括号括起来的内容
              # (即HTML/XML标签)
      )       # 前缀结束
      .*      # 匹配任意文本
      (?=     # 断言要匹配的文本的后缀
      <\/\1>  # 查找尖括号括起来的内容
              # 查找尖括号括起来的内容
      )       # 后缀结束

        a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

十、其他

        上边已经描述了构造正则表达式的大量元素,但是还有很多没有提到的东西。下面是一些未提到的元素的列表,包含语法和简单的说明。

        我承认,我之前的说法可能给你带来了误解。我提及的‘10分钟’并非实际所需时间,而是为了鼓励你保持兴趣和耐心继续阅读。既然你已经深入阅读至此,这足以证明我的初衷已经达成。对于可能给你带来的任何困扰或疑惑,我深感抱歉,并诚挚地感谢你的理解和持续的关注。”

  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值