返回介绍

7.4 正则达达示中的模式修正符

发布于 2025-01-30 22:11:33 字数 7638 浏览 0 评论 0 收藏 0

我们通过元字符和原子完成了正则表达式的入门。但有一些特殊情况我们依然需要来处理。

如果 abc 在第二行的开始处如何匹配?
我不希望正则表达示特别贪婪的匹配全部,只匹配一部分怎么办?

这个时候,我们就需要用到下面的这些模式匹配来增强正则的功能。

常用的模式匹配符有:

模式匹配符功能
i模式中的字符将同时匹配大小写字母。
m字符串视为多行
s将字符串视为单行,换行符作为普通字符。
x将模式中的空白忽略。
A强制仅从目标字符串的开头开始匹配。
D模式中的美元元字符仅匹配目标字符串的结尾。
U匹配最近的字符串。

模式匹配符的用法如下:

/ 正则表达示/模式匹配符

模式匹配符是放在这句话的最后的。例如:

/\w+/s

格式我们清楚了,接下来最主要的是加强对于模式匹配符使用的理解和记忆。我们通过代码来理解加上和不加模式匹配符有何区别。

i 不区分大小写

<?php
//在后面加上了一个 i
$pattern = '/ABC/i';

$string = '8988abc12313';

$string1 = '11111ABC2222';

if(preg_match($pattern, $string, $matches)){
echo '匹配到了,结果为:';
var_dump($matches);
}else{
echo '没有匹配到';
}
?>

结论,不论是$string 还是$string1 全都匹配成功了。因此,在后面加上了 i 之后,在匹配的时候可以不区分大小写。

m 视为多行

正则在匹配的时候,要匹配的目标字符串我们通常视为一行。

“行起始”元字符(^)仅仅匹配字符串的起始,“行结束”元字符($)仅仅匹配字符串的结束。

当设定了此修正符,“行起始”和“行结束”除了匹配整个字符串开头和结束外,还分别匹配其中的换行符的之后和之前。

注意:如果要匹配的字符串中没有“\n”字符或者模式中没有 ^ 或 $,则设定此修正符没有任何效果。

我们通过实验和代码来验证一下这个特点:

第一次匹配,你会发现匹配不成功:

<?php

$pattern = '/^a\d+/';

$string = "我的未来在自己手中我需要不断的努力
a9 是一个不错的字符表示
怎么办呢,其实需要不断奋进";

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

第二次匹配,我们加上 m 试试:

<?php

$pattern = '/^a\d+/m';

$string = "我的未来在自己手中我需要不断的努力
a9 是一个不错的字符表示
怎么办呢,其实需要不断奋进";

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

结果:

哦耶!匹配成功了。/^a\d+/ 匹配的内容是 a9,必须得在行开始处。在第二行也被匹配成功了。

document/2015-09-04/55e9579575df0

s 视为一行

如果设定了此修正符,模式中的圆点元字符(.)匹配所有的字符,包括换行符。

第一次,不加模式匹配符 s:

<?php

$pattern = '/新的未来.+\d+/';

$string = '新的未来
987654321';

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

?>

第二次,在正则表达示后面加上模式匹配符 s:

<?php

$pattern = '/新的未来.+\d+/s';

$string = "新的未来
987654321";

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

?>

结果如下,匹配成功!

document/2015-09-04/55e9622e85495

结论:

  1. 因为在新的未来,未来后面有一个换行
  2. 而.(点) 是匹配非空白字符以外的所有字符。因此,第一次不成功
  3. 第二次,加上了 s 模式匹配符。因为,加上后.(点)能匹配所有字符。

x 忽略空白字符

  1. 如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略。
  2. 未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。

我们先来实验一下忽略空白行等特性:

<?php

$pattern = '/a b c /x';

$string = '学英语要从 abc 开始';

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

?>

这样也能匹配成功。
document/2015-09-04/55e9644052bd6

在$pattern 里面有空格,每个 abc 后面有一个空格。而$string 里面没有空格。
所以 x 忽略空白字符。

而第二句话从字面上比较难理解,

<?php
//重点观察这一行
$pattern = '/a b c #我来写一个注释
/x';

$string = '学英语要从 abc 开始';

if (preg_match($pattern, $string, $matches)) {
echo '匹配到了,结果为:';
var_dump($matches);
} else {
echo '没有匹配到';
}

?>

结果也匹配成功了!

document/2015-09-04/55e9644052bd6

我们发现,x 的第二个特性是忽略:#字符和下一个换行符之间的字符也被忽略。

e 将匹配项找出来,进行替换

  • e 模式也叫逆向引用。主要的功能是将正则表达式括号里的内容取出来,放到替换项里面替换原字符串。

  • 使用这个模式匹配符前必须要使用到 preg_replace()。

    mixed preg_replace ( mixed $正则匹配项 , mixed $替换项 , mixed $查找字符串)

  • preg_replace 的功能:使用$正则匹配项变,找到$查找字符串变量。然后用$替换项变量进行替换。

在正式讲解前我们回顾一下之前的知识,我们故意把每个要匹配的原子外面都加上括号:

<?php
//加上了括号
$pattern = '/(\d+)([a-z]+)(\d+)/';

$string = '987abc321';

if (preg_match($pattern, $string, $match)) {
echo '匹配到了,结果为:';
var_dump($match);

} else {
echo '没有匹配到';
}
?>

我们来看看结果:
document/2015-09-05/55ea63c27b9e2

这是我们之前讲括号的时候:匹配到的内容外面有括号。会把括号里面的内容,也放到数组的元素里面。如图中的:987、abc、321。

我们接下来看正则表达示中的 e 模式:

<?php
$string = "{April 15, 2003}";

//'w'匹配字母,数字和下划线,'d'匹配 0-99 数字,'+'元字符规定其前导字符必须在目标对象中连续出现一次或多次
$pattern = "/{(\w+) (\d+), (\d+)}/i";

$replacement = "\$2";

//字符串被替换为与第 n 个被捕获的括号内的子模式所匹配的文本
echo preg_replace($pattern, $replacement, $string);

?>

我们看看执行结果:
document/2015-09-05/55ea647e995b4

结论:

  1. 上例中\$2 指向的是正则表达示的第一个(\d+)。相当于把 15 又取出来了
  2. 替换的时候,我写上\$2。将匹配项取出来,用来再次替换匹配的结果。

U 贪婪模式控制

正则表达式默认是贪婪的,也就是尽可能的最大限度匹配。

我们来看看正则表达示是如何贪婪的:

<?php
$pattern = '/<div>.*<\/div>/';

$string = "<div>你好</div><div>我是</div>";

if (preg_match($pattern, $string, $match)) {
echo '匹配到了,结果为:';
var_dump($match);
} else {
echo '没有匹配到';
}

?>

我们来看看结果,得到如下结论。它从“

你好”直接匹配到了“我是”。进行了最大范围的匹配。

document/2015-09-05/55ea7253227a5

同样一段代码我们再加大写的 U,再看看效果:

<?php
$pattern = '/<div>.*<\/div>/U';

$string = "<div>你好</div><div>我是</div>";

if (preg_match($pattern, $string, $match)) {
echo '匹配到了,结果为:';
var_dump($match);
} else {
echo '没有匹配到';
}

?>

document/2015-09-05/55ea72bc445e6

我们发现,只匹配出来了:

<div>你好</div>

这样,把正则的贪婪特性取消掉。让它找到了最近的匹配,就 OK 了。

A 从目标字符串的开头开始匹配

此模式类似于元字符中的^(抑扬符)效果。

<?php

$pattern = '/this/A';

$string = 'hello this is a ';
//$string1 = 'this is a ';

if (preg_match($pattern, $string, $match)) {
echo '匹配到了,结果为:';
var_dump($match);
} else {
echo '没有匹配到';
}

?>

结论:

  1. 如果加 A 模式修正符的时候匹配不出来$string,不加时能匹配出来
  2. 如果加上了 A 模式修正符的时候能匹配出来$string1,因为必须要从开始处开始匹配

D 结束$符后不准有回车

如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前。

<?php

$pattern = '/\w+this$/';

//$pattern1 = '/\w+this$/D';

$string = "hellothis
";

if (preg_match($pattern, $string, $match)) {
echo '匹配到了,结果为:';
var_dump($match);
} else {
echo '没有匹配到';
}

?>

结果展示:
document/2015-09-05/55ea790f3df3f

结论:

  1. 如 pattern 在匹配$string 的时候,$string 的字符串 this 后有一个回车。在没有加 D 匹配符的时候也能匹配成功
  2. 如 pattern 在匹配$string 的时候,加上了 D。$string 的字符串 this 后有空格,匹配不成功。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文