跳至主要內容

正则表达式笔记

大约 8 分钟

正则表达式笔记

参考教程 https://www.runoob.com/regexp/regexp-tutorial.htmlopen in new window

正则表达式通常用于表示满足特定规则的字符串, 因此可用于匹配文本内容, 并从中提取信息

正则表达式基本内容

普通字符

正则表达式中, 认为数字, 字母, unicode 文字以及非元字符的符号为普通字符
对于表达式中的普通字符, 表现与一般的字符串匹配相同, 仅当文本的字符以及相对位置与其相同才能通过匹配

转义字符

与一般格式化字符串相同, 正则表达式中可通过转义符 \ 加内容表示特殊字符

通常可用于与元字符组合, 表示其原本代表的字符

此外还可用于表示非打印字符, 常用的有

  • \n 匹配换行符
  • \t 匹配制表符
  • \xNN 匹配 ASCII 字符, 其中 XX 为字符的十六进制编码
  • \uNNNN 匹配 Unicode 字符, 其中 XXXX 为字符的十六进制编码

元字符

正则表达式中主要包含如下元字符, 这些元字符都具有特殊含义, 需要通过 \ 转义才能表示原本代表的字符

虽然部分情况下直接使用元字符是合法的, 但为了避免歧义, 建议表示任意元字符时都需要转义

字符类

普通字符只能表示一个位置的一个字符, 可通过字符类表示字符, 此时该位置能够使用一类字符匹配
如果希望匹配一类特定特征的字符串, 应使用或运算

内置字符类

  • \<内容> 表示一类相同性质的字符, 常用的有
    • \w 所有字母, 数字, 下划线, \W 则取反
    • \d 表示所有数字, \D 则取反
    • \s 表示所有空格, 换行等空白字符, \S 则取反
  • 以元字符或 \<内容> 表示特殊位置, 不能被重复限定修饰
    • $ 文本内容的结尾位置, 不匹配具体字符
    • ^ 文本内容的起始位置, 不匹配具体字符, 例如 ^...$ 将使用整个文本内容进行匹配
    • \b 表示与单词相邻的空格或边界, 例如 \b\w+\b 将匹配所有单词
    • \B 表示不与空格相邻的单词, 例如 er\B 可以匹配 verb 中的 erb
  • 元字符 . 表示除换行 \n 外的所有字符

自定义字符类

  • 通过 [] 包裹一系列普通字符或内置字符类, 此时该位置可以匹配其中的任意一个字符
    • 例如 [123] 可以匹配 1, 2, 3 三个字符中任意一个
  • 当出现 ^ 时, 将表示取反, 即该位置可以匹配除其中出现字符外的任意字符
    • 例如 [^123] 可以匹配除 1, 2, 3 外的任意字符
  • 对于在编号上连续的一系列 ASCII 或 unicode 字符, 可通过 - 连接首尾表示
    • 例如 [0-9] 匹配所有数字, [a-z] 匹配所有小写字母
    • 例如 [!-/ :-@ \[-` {-~] 匹配空格与所有 ASCII 符号 (注意分了四段, 存在空格是为了方便观察, 如果仅匹配符号可删去)

重复限定

重复限定是一种修饰, 用于修饰其左侧最邻近的包括字符类在内的任意字符

  • {n} 必须重复匹配 n 次, 例如 o{2}oo 匹配
  • {n,} 至少匹配 n 次, 例如 o{2,}ooo 匹配, 但与 o 不匹配
  • {n,m} 至少匹配 n 次, 但最多匹配 m
  • 元字符 *, 匹配零次或多次, 等价于 {0,}
  • 元字符 +, 匹配一次或多次, 等价于 {1,}
  • 元字符 ?, 匹配零次或一次, 等价于 {0,1}

在重复限定中, 正则表达式总是遵守让左侧的字符匹配尽可能多次的原则, 即贪婪原则

内容选择

通过 () 包裹任意正则表达式, 可以表示

  • 对被包裹正则表达式匹配内容的选择
  • 表示一类满足被包裹正则表达式的子字符串

或运算

  • 通过 | 连接两个正则表达式可用于表示匹配任意一个表达式, 且以左侧的表达式优先
    • 例如表达式 (\d+|\w+) 匹配字符串 12A 时, 将分别匹配 12A
  • 或运算通常与内容选择混合使用, 以此表示部分位置的或运算
    • 例如表达式 (fi|da|ba)sh 可与字符串 fish, dash, bash 匹配

重复内容选择

内容选择也可以配合重复限定使用, 表示重复出现的一类子字符串

  • 通过 (...)? 可用于表示该子字符串允许出现一次或不出现

提取选择内容

在使用正则表达式的字符串替换功能时, 还可在替换字符串中使用 $n 表示选择内容, 实现选择内容的提取

  • n 为提取第 n 个选择内容, 从 1 开始索引
  • 只有最外层的内容选择能被提取, 嵌套在内部的不能被提取
    • 例如 ((da|fi)sh)er 匹配字符串 fisher 时, $1 提取到的是 fish
  • 对于重复内容选择, 只会提取最右侧的选择内容, 如果内容提取则为空
    • 例如 (\d+A)+ 匹配字符串 12A24A 时, $1 提取到的是 24A
    • 例如 (\d{3})?\w 匹配字符串 A 时, $1 提取到的是空
  • 当使用 (?:) 表示内容选择时, 即将 ?: 添加在正则表达式前修饰选择, 不会提取此处选择的内容
    • 类似的定位断言并不用于选择, 自然也不能被提取
  • 对于特定的编程语言下的实现, 提取内容可能体现为返回的匹配结果数组, 通常索引 0 为整个被匹配的字符串

引用选择内容匹配

除了提取被选择的内容, 还可以将被选择的内容用于匹配

  • 使用 \n 可引用第 n 个选择内容, 注意 n 为数字且索引规则与提取选择内容相同
  • 仅当子字符串与之前提取的选择内容完全相同才能通过匹配
  • 对于重复内容选择, 同样只会使用最右侧的选择内容
  • 例如 (\d+A)+ \1 匹配字符串 12A24A 24A 通过, 但不匹配字符串 12A24A 12A

定位断言

定位断言是一种特殊的定位方法, 不表示具体字符, 用于表示匹配内容位于特定类型的子字符串旁边
此处仅介绍其中的先行正向断言, 关于更多介绍可参考 https://www.runoob.com/w3cnote/reg-lookahead-lookbehind.htmlopen in new window

先行正向断言 (?=...), 其中 ... 为断言正则表达式

  • 表示满足断言正则表达式的子字符串左侧位置, 且对其右侧没有限制
  • 例如 a(?=\d) 可以匹配右侧与数字相邻的 字母 a, 如 a1, 但不匹配 1aab
  • 允许使用多个断言修饰同一个位置
  • 类似的还有负向正向断言 (?!...), 此时子字符串不能满足给出的断言正则表达式

一般通过以下形式使用断言

  • ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)\w{6,18}$ 用于匹配任意至少包含一个大小写字母与数字的, 满足 \w 要求, 且长度在 6-18 的字符串
    • 其中各项断言如 (?=.*[a-z]) 中, .* 表明限定内容位置不限, [a-z] 则表明要求出现的内容
      通过 (?=.*<regex>) 的方式使用断言, 可用于表示对于内容任意位置应至少出现一处符合正则表达式 <regex> 的子字符串
    • 去除断言剩余的 ^\w{6,18}$ 则表明对输入内容的基本要求
    • 以上方法主要用于密码的匹配, 通过分解为 ^(?=.*[a-z]).+$$\w{6,8}$ 等可实现对密码各项要求的单独检查
  • ^(?!.*\.min\.css$)(.+)\.css$ 用于匹配以 .css 为结尾, 但不以 .min.css 为结尾文件的文件名
    • 其中通过断言 (?!.*\.min\.css$) 提前排除了所有满足 .*\.min\.css$ 的字符串
      通过 ^(?=.*<regex>) 的方式使用断言, 可用于排除一类字符串中的特定子类
    • 结尾不使用断言, 注意, 正向断言一般与 .* 等任意字符匹配配合才有意义, 否则直接匹配即可不需要断言
  • ([^;]+)(?=\.min\.css) 从一串以 ; 为间隔的文件名列表字符串中, 提取以 .min.css 为后缀的文件名

修饰符

修饰符可用于指定正则表达式的匹配策略, 对于特定编程语言下的实验, 可能体现为匹配模式

  • 不区分大小写 i
  • 全局匹配 g 匹配时对所有输入内容进行匹配
  • 多行匹配 m 元字符 ^, $ 改为匹配内容各行的开头与结尾, 相当于对各行分别匹配
  • 特殊控制 s 元字符 . 将匹配所有字符 (默认 . 不包含换行 \n)

在正规表示正则表达式时, 会使用 /<regex>/[modify] 的形式

  • <regex> 正则表达式主题
  • [modify] 可选的修饰符

常用正则表达式

参考正则表达式例子 * https://www.runoob.com/regexp/regexp-example.htmlopen in new window
* https://docs.python.org/zh-cn/3/library/re.html#regular-expression-examplesopen in new window

正则表达式测试 https://www.jyshare.com/front-end/854/open in new window

  • [\u4E00-\u9FA5] 表示中文字符集
  • ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\x20-\x7E]{8,20}$ 表示必须包含字母与数字, 由 8 到 20 个可打印 ASCII 字符组成的密码