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"。
图示化理解:
-
贪婪匹配:
字符串
a123b456b-> 贪婪正则/a.*b/-> 匹配到整个a123b456b。 -
非贪婪匹配:
字符串
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)/- 这将捕获
a、b、c,它们分别存储在捕获组 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",因此它们符合正向否定断言的条件。
总结
正向肯定断言
(?=...): 匹配某个位置后必须跟随的内容,但不包括该内容在最终匹配中。例如,匹配某个字符后跟随特定字符但不包含它。正向否定断言
(?!...): 匹配某个位置后不能跟随的内容。例如,匹配某个字符,条件是它后面不允许跟随特定字符。