PHP 正则表达式 修正符【m s x e ? (?i)】内部修正符 贪婪模式 后向引用 断言【总结篇】

1.正则表达式修正符

++在 PHP 中,正则表达式中的修正符(modifier)可以改变模式的行为++,使得其功能更加灵活。

1. m 修正符(多行模式)

  • 作用 :在多行模式下,^$ 元字符除了匹配整个字符串的开头和结尾外,还可以匹配每一行的开头和结尾
  • 举例"Hello\nWorld",当使用 /^World/m 时,^ 会匹配 "World" 这一行的开头,而不仅仅匹配整个字符串的开头。

2. s 修正符(单行模式)

  • 作用 :使 .(点号)可以匹配所有字符,包括换行符(\n 。如果不加此修正符,. 默认匹配除换行符外的所有字符。
  • 举例 :假设有字符串 "Hello\nWorld",使用 /Hello.World/s 时,. 可以匹配换行符,因此该正则表达式可以成功匹配整个字符串。

3. x 修正符(忽略模式中的空白字符)

  • 作用 :开启"扩展模式",忽略模式中的空白字符 (除非在字符类 [] 内或被反斜杠转义),还会忽略未转义的 # 后的内容直到该行结束。通常用于编写更易读的正则表达式。
  • 举例 :正则表达式 /a b c/x 实际上会被解析为 /abc/,即空格被忽略。

4. e 修正符(已废弃,自 PHP 5.5.0 起)

  • 作用 :该修正符曾用于 preg_replace() 函数,允许在替换时对替换字符串中的反向引用进行 PHP 代码的执行。由于存在安全性问题,该修正符已被弃用。
  • 替代方案 :可以使用 preg_replace_callback() 来实现类似功能。++(后文介绍)++

5. i 修正符

  • 作用: 匹配过程中不区分大小写。
举例:/abc/i可以匹配"AbC"

6. 非贪婪匹配(使用 ? 实现)

  • 贪婪匹配 :正则表达式中的 *+? 默认是贪婪的,即它们会匹配尽可能多的字符。
  • 非贪婪匹配 :在贪婪量词后加 ?,可以使匹配变为非贪婪(也称为"最小匹配"),即匹配尽可能少的字符。
  • 举例
    • 贪婪匹配:/a.*b/ 会匹配从第一个 a 开始到最后一个 b 之间的所有内容。
    • 非贪婪匹配:/a.*?b/ 只匹配第一个 a 和第一个 b 之间的最少字符。
总结
  • m:多行匹配,^$ 可以匹配每行的开头和结尾。
  • s:单行模式,. 可以匹配包括换行符在内的所有字符。
  • x:忽略正则中的空白字符,并允许使用注释。
  • e:在替换时允许执行 PHP 代码,现已弃用。
  • ?:与 *+ 搭配使用可以实现非贪婪匹配。

2.贪婪匹配与非贪婪匹配

在正则表达式中,贪婪匹配非贪婪匹配 是两个重要的概念,++它们决定了匹配操作在处理多个可能的匹配项时的行为。++

1. 贪婪匹配

贪婪匹配(Greedy Matching)是正则表达式的默认行为,即在匹配过程中,量词如 *, +{n,} 会尝试匹配尽可能多的字符。它们会从最早出现的匹配点开始,然后继续匹配更多字符,直到满足整个模式或者没有更多可以匹配的字符

  • 模式 : /a.*b/
  • 含义 :
    • a:匹配字符 a
    • .*:匹配任意字符(除了换行符),匹配尽可能多的字符。
    • b:匹配字符 b
  • 贪婪行为.* 尽可能多地匹配字符,直到遇到最后一个可能的 b
  • 例子 :
    • 字符串:"a123b456b"
    • 匹配结果:"a123b456b"

在贪婪匹配中,.* 会从第一个 a 开始,匹配尽可能多的字符,直到遇到最后一个 b 。因此,它匹配整个 "a123b456b"

2. 非贪婪匹配

非贪婪匹配(Lazy Matching),也称为"最小匹配",是通过在量词后面加上 ? 来实现的。非贪婪匹配的行为是尽可能少地匹配字符,在满足整个模式的前提下只匹配最少的字符

  • 模式 : /a.*?b/
  • 非贪婪行为.*? 尽可能少地匹配字符,直到遇到第一个 b 就停止。
  • 例子 :
    • 字符串:"a123b456b"
    • 匹配结果:"a123b"

在非贪婪匹配中,.*? 从第一个 a 开始,匹配尽可能少的字符,直到遇到第一个 b 就停止。因此,它只匹配 "a123b"

图示化理解:

  1. 贪婪匹配:

    字符串 a123b456b -> 贪婪正则 /a.*b/ -> 匹配到整个 a123b456b

  2. 非贪婪匹配:

    字符串 a123b456b -> 非贪婪正则 /a.*?b/ -> 匹配到 a123b(尽量少匹配)。

总结

  • 贪婪匹配 : /a.*b/ 尽可能多地匹配,从第一个 a 开始匹配到最后一个 b
  • 非贪婪匹配 : /a.*?b/ 尽可能少地匹配,从第一个 a 开始匹配到第一个 b

3.(?i) 修正符的解释

在 PHP 的正则表达式中,(?i) 是一个**++内部修正符,用于指定在正则表达式的某个部分中忽略大小写进行匹配++** 。它等同于我们在正则表达式外部使用修正符 i,只是 (?i) 修正符的效果可以局部应用于特定的子模式

1. 用法说明
  • (?i):内部修正符,表示该部分不区分大小写。
  • 区别 :如果使用外部的 i 修正符,则整个模式都不区分大小写;但 (?i) 修正符只影响它所在的子模式。
2. 示例
  • 外部修正符: /abc/i
    • 模式 /abc/i 中的 i 修正符表示整个正则表达式不区分大小写。
    • 它将匹配 "abc""ABC""aBc" 等所有大小写组合。
  • 内部修正符: /a(?i)bc/
    • 模式 /a(?i)bc/ 中的 (?i) 只对其后面的 bc 起作用。
    • 它将匹配 "abc""aBC",但不会匹配 "ABC""Abc",因为 a 仍然区分大小写。
3. 结合其它修正符

与外部修正符相似,内部修正符还包括:

  • x:忽略正则表达式中的空白字符。
  • m:多行模式,使 ^$ 匹配行的开头和结尾,而不仅是字符串的开头和结尾。
  • s:单行模式,使 . 匹配包括换行符在内的所有字符。
  • U:非贪婪模式,默认使用非贪婪匹配。

4.后向引用(Backreference)

后向引用是一种可以在正则表达式中引用之前捕获的子模式的方法。通过在模式中添加圆括号 () 来定义捕获组,PHP 会自动为每个捕获的子模式分配一个编号,++这个编号从 1 开始。在后续的模式中,可以使用反斜杠 \n(其中 n 是捕获组的编号)来引用之前的匹配。++

1. 示例
  • 模式: /(a)(b)(c)/

    • 这将捕获 abc,它们分别存储在捕获组 1、2、3 中。
    • 可以使用后向引用来重新引用这些捕获的部分,例如 /\1\2\3/ 将匹配 abc
  • 示例:

    • 正则表达式 /(a)(b)\1\2/ 将匹配类似 ab 后跟 ab 的字符串。
    • 在字符串 "abxab" 中,模式 /(a)(b)\1\2/ 将匹配 "abab"
2. 非捕获组

有时我们只想匹配某些内容,但不希望将其存储在捕获组中。这时可以使用非捕获元字符 (?:) 来忽略捕获。

  • 示例: (?:abc) 会匹配 "abc",但不会将其存储为捕获组,因此不会占用编号。

其他的非捕获组符号包括:

  • (?=...)正向肯定断言,匹配在指定位置后必须跟随的内容。
  • (?!...)正向否定断言,匹配在指定位置后不能跟随的内容。
总结
  • (?i):内部修正符,指定模式中的某部分不区分大小写。
  • 后向引用:使用 () 捕获匹配内容,并通过 \n 进行引用。
  • 非捕获组:使用 (?:) 或断言符号来匹配但不保存相关内容。

5.正则表达式中的断言

++断言用于定义在某个位置前后必须或不能出现的内容,称为零宽断言++(zero-width assertions),因为它们只检查条件,而不会消耗字符。

1. 正向肯定断言(?=...)

正向肯定断言表示匹配某位置后面必须跟随的内容,但这些内容本身并不会成为匹配结果的一部分。

  • 格式 : (?=...)
  • 作用: 确保在当前位置之后,有满足断言条件的字符出现。
例子:
  • 正则表达式:/\d(?=\D)/

    • 含义:匹配一个数字(\d),条件是它后面跟随一个非数字字符(\D),但不包含这个非数字字符在匹配结果中。
    • 示例字符串:"123a4b"
    • 匹配结果:["3", "4"]

    "123a4b" 中,"3" 后跟的是字母 "a""4" 后跟的是字母 "b",所以它们符合正向肯定断言的条件。

2. 正向否定断言(?!...)

正向否定断言表示匹配某位置后面不能跟随的内容,即当前位置后如果有符合条件的字符出现,匹配将失败。

  • 格式 : (?!...)
  • 作用: 确保在当前位置之后,不能有满足断言条件的字符。
例子:
  • 正则表达式:/\d(?!\d)/

    • 含义:匹配一个数字,条件是它后面不能跟随另一个数字(即确保当前匹配的是最后一个连续数字)。
    • 示例字符串:"123a456b"
    • 匹配结果:["3", "6"]

    "123a456b" 中,"3" 后面不是数字,而是字母 "a""6" 后面也不是数字,而是字母 "b",因此它们符合正向否定断言的条件。

总结
  • 正向肯定断言 (?=...): 匹配某个位置后必须跟随的内容,但不包括该内容在最终匹配中。例如,匹配某个字符后跟随特定字符但不包含它。

  • 正向否定断言 (?!...): 匹配某个位置后不能跟随的内容。例如,匹配某个字符,条件是它后面不允许跟随特定字符。

相关推荐
canyuemanyue5 分钟前
C++单例模式
开发语言·c++·单例模式
BABA889118 分钟前
学生成绩查询系统设计与实现
php
秋恬意20 分钟前
Java 反射机制详解
java·开发语言
黑不溜秋的23 分钟前
C++ 模板专题 - 标签分派(Tag Dispatching)
开发语言·c++·算法
skywind32 分钟前
为什么 C 语言数组是从 0 开始计数的?
c语言·开发语言·网络·c++
尘浮生1 小时前
Java项目实战II基于Spring Boot的火锅店管理系统设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·微信小程序·旅游
wrx繁星点点1 小时前
桥接模式:解耦抽象与实现的利器
android·java·开发语言·jvm·spring cloud·intellij-idea·桥接模式
千汇数据的老司机1 小时前
网络安全、数据监测、数据预警的可视化大屏
网络·安全·web安全
千里马-horse1 小时前
在OpenCL 中输出CLinfo信息
开发语言·c++·算法·opencl·1024程序员节