一、基础概念

正则表达式是一种用于描述文本模式的工具。它是一个字符序列,用于定义搜索模式,可用于文本搜索、文本替换、文本验证等操作。

二、字符匹配

  1. 普通字符匹配
    • 普通字符(如字母、数字、大部分标点符号)在正则表达式中匹配其自身。例如,正则表达式abc会匹配文本中连续出现的abc。
  2. 特殊字符匹配(元字符)
    • 点号(.)
      • 匹配除换行符\n之外的任意单个字符。例如,a.c可以匹配abc、a c、a!c等。
    • 字符类([])
      • 用于匹配一组字符中的任意一个。例如,[abc]可以匹配a、b或者c。
      • 可以使用范围表示法,如[a - z]匹配所有小写字母,[A - Z]匹配所有大写字母,[0 - 9]匹配所有数字。范围可以组合,如[a - zA - Z0 - 9]匹配所有字母和数字。
    • 否定字符类([^])
      • 匹配不在字符类中的任意一个字符。例如,[^abc]会匹配除a、b、c之外的任意字符。
    • 预定义字符类(快捷方式)
      • \d:匹配任何数字,等价于[0 - 9]。
      • \D:匹配任何非数字字符,等价于[^0 - 9]。
      • \w:匹配任何单词字符(字母、数字、下划线),等价于[a - zA - Z0 - 9_]。
      • \W:匹配任何非单词字符,等价于[^a - zA - Z0 - 9_]。
      • \s:匹配任何空白字符(空格、制表符、换行符等),等价于[ \t\n\r\f\v]。
      • \S:匹配任何非空白字符,等价于[^ \t\n\r\f\v]。

三、重复匹配

  1. 量词(指定匹配次数)
    • 星号(*)
      • 匹配前面的元素零次或多次。例如,a*可以匹配空字符串、a、aa、aaa等。
    • 加号(+)
      • 匹配前面的元素一次或多次。例如,a+可以匹配a、aa、aaa等,但不能匹配空字符串。
    • 问号(?)
      • 匹配前面的元素零次或一次。例如,a?可以匹配空字符串或者a。
    • 花括号({})
      • 用于指定前面元素的精确匹配次数。例如,a{3}匹配aaa。
      • 可以指定范围,如a{2,4}匹配aa、aaa或者aaaa。也可以使用开放范围,如a{2,}匹配aa、aaa、aaaa等,至少匹配两次。

四、位置匹配

  1. 行首和行尾匹配
    • 脱字符(^)
      • 在正则表达式的开头使用时,表示匹配行首。例如,^abc会匹配以abc开头的行。如果设置了多行模式(在某些编程语言中有相关选项),它会匹配每一行的开头。
    • 美元符号($)
      • 在正则表达式的结尾使用时,表示匹配行尾。例如,abc$会匹配以abc结尾的行。同样,在多行模式下会匹配每一行的结尾。
  2. 单词边界匹配
    • \b
      • 匹配单词的开头或结尾。例如,\bcat\b会匹配单独的单词cat,而不会匹配category中的cat部分。它的边界判断是基于\w和\W的转换,即从单词字符(\w)到非单词字符(\W)或者反之的位置。
    • \B
      • 与\b相反,匹配非单词边界。例如,\Bcat\B不会匹配单独的cat单词,而是可能匹配像bcatd这样的字符串中的cat部分。

五、分组匹配

  1. 括号(())的作用
    • 用于分组,可以将多个字符或表达式组合在一起,当作一个整体进行处理。例如,(abc)+会匹配abc、abcabc等。
    • 分组还可以用于捕获匹配的内容,方便后续提取或替换。例如,在(\d{3})(\d{4})中,\d{3}和\d{4}分别被分组,在替换操作中可以通过\1和\2引用这两个分组。\1引用第一个分组匹配的内容,\2引用第二个分组匹配的内容。
  2. 非捕获分组
    • 有时候我们只想分组用于逻辑上的组合,而不想捕获其内容用于后续引用。可以使用(?:)来创建非捕获分组。例如,(?:abc)+的功能和(abc)+类似,但不会创建可引用的捕获组。

六、选择匹配和逻辑匹配

  1. 竖线(|)
    • 用于表示选择关系,类似于逻辑或。例如,a|b可以匹配a或者b。可以组合更复杂的表达式,如(abc|def)可以匹配abc或者def。
  2. 环视(零宽度断言)
    • 正向前瞻(?=)
      • 用于匹配某个模式后面跟着的内容。例如,a(?=b)会匹配a,但前提是a后面必须跟着b,并且b不被包含在匹配结果中。这是一种零宽度的匹配,即它只检查是否满足条件,但不消耗后面的字符。
    • 负向前瞻(?!)
      • 与正向前瞻相反,用于匹配某个模式后面不跟着的内容。例如,a(?!b)会匹配a,但前提是a后面不能跟着b。
    • 正向后顾(?<=)
      • 用于匹配某个模式前面跟着的内容。例如,(?<=a)b会匹配b,但前提是b前面必须是a。不过要注意,不是所有的正则表达式引擎都支持正向后顾,因为它在实现上相对复杂。
    • 负向后顾(?<!)
      • 与正向后顾相反,用于匹配某个模式前面不跟着的内容。例如,(?<!a)b会匹配b,但前提是b前面不能是a。同样,其支持情况因引擎而异。

七、转义字符

  1. 反斜杠(\)的作用
    • 用于转义特殊字符,使其匹配自身。例如,要匹配星号*本身,需要写成\*。
    • 也用于一些特殊的转义序列,如\n(换行符)、\t(制表符)、\r(回车符)等。在处理文本中的换行等特殊格式时很有用。
    • 用于一些特殊的字符序列表示,如\d(数字)、\w(单词字符)等前面提到的预定义字符类,实际上是通过反斜杠来定义特殊的匹配模式。

八、贪婪匹配与非贪婪匹配

  1. 贪婪匹配
    • 贪婪匹配是指正则表达式尽可能多地匹配字符。例如,对于字符串aabbb和正则表达式a.*b,贪婪匹配的结果是aabbb,因为.*会尽可能多地匹配中间的字符。
  2. 非贪婪匹配(懒惰匹配)
    • 非贪婪匹配(也称为懒惰匹配)是指正则表达式尽可能少地匹配字符。在量词后面添加?可以实现非贪婪匹配。例如,对于同样的字符串aabbb和正则表达式a.*?b,非贪婪匹配的结果是aab,因为.*?会尽可能少地匹配中间的字符,直到遇到第一个b就停止。

九、正则表达式的应用场景

  1. 文本搜索
    • 可以在大量文本中查找符合特定模式的内容。例如,在一篇文章中查找所有的电子邮件地址、电话号码、网址等。
  2. 文本验证
    • 用于验证用户输入的内容是否符合特定格式。如验证密码是否符合强度要求(包含字母、数字、特殊字符,长度在一定范围内等),验证身份证号码、银行卡号码等格式是否正确。
  3. 文本替换
    • 可以将文本中符合特定模式的内容替换为其他内容。例如,将文章中的所有电话号码格式统一,或者将敏感信息(如身份证号码部分数字)替换为星号等。

如何在不同编程语言中使用正则表达式?

列举一些常见的正则表达式错误

分享一些学习正则表达式的资源

更多推荐