正则表达式的常用模式

正则表达式的常用模式

模式(Pattern Modifiers)就是可以改变表达行为的字符,用来关闭或打开模式(Pattern Modifiers)就是可以改变表达行为的字符,用来关闭或打开,下面介绍一些基本修饰符及常用模式。

1.忽略大小写模式(i)

在此模式下,正则匹配将不区分待匹配内容的大小写,这在HTML里常用。由于HTML本身的容错性很好,对大小写混用有很好的兼容处理能力,也就经常会出现无论是标签还是内容的大小写混乱问题,这时采用这种模式就能很好地处理这种情况。示例代码如下:

<?php
$str = '<div>gG</Div>';
$reg = '#<div>gg<\/div>#i';
if(preg_match($reg, $str, $arr)){
    echo "匹配成功".$arr[0];
}else{
    echo "匹配不成功";
}

运行结果为:

匹配成功<div>gG</Div>

忽略大小写是针对整个表达式而言,而不仅仅是欲匹配的部分。所以,可以在代码里放心地使用此修饰符。但是出于效率的考虑,尽量让正则表达式所指示的范围更精确。

注意,修饰符对整个表达式有效。如果只想修饰部分表达式,可以使用PCRE的内部选项——”局部修饰符”。比如下面表达式仅匹配abc和abC,而不会匹配Abc:

#ab(?i)c#

也就是说,(?i) 只对它后面的字符c起作用。

2.多行模式(m)

在讲起始和终止符时提过:“勾选Multiline选项,即多行选项。如果选中了这个选项,^$的意义就变成匹配行的开始处和结束处,否则将把整个输入视作一个字符串,忽视换行符。”也就是说,正则表达式默认开始^和结束只是对于正则字符串,如果在修饰符中加上m,开始和结束将会指字符串的每一行:即每一行的开头就是^,结尾就是$

需要【注意】,m表示多行匹配,而非跨行匹配仅当表达式中出现^,$中至少一个元字符且字符串有换行符\n时,m修饰符才起作用,否则被忽略,如下代码所示:

<?php
$str = "this is reg
Reg
this is
regexp turtor,oh reg";
if(preg_match_all('#.*reg$#mi', $str, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

在预想中,.*reg$就是以reg结尾的行,由于加了m修饰符,按理应该匹配第一行和第四行,但实际结果呢?如下所示:

array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(20) "regexp turtor,oh reg"
  }
}

可以看出,只匹配最后一行的reg,而第一行虽然也是以reg结尾,但是并没有被匹配。这里用到mi,也就是把修饰符m和i组合使用。事实上,本例中即使去掉m修饰符,最终结果也是一样,这说明$只能表示最后一行。把正则表达式改为:

#^t.*#mi

匹配的结果将是:

<?php
$str = "this is reg
Reg
this is
regexp turtor,oh reg";
if(preg_match_all('#^t.*#mi', $str, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

匹配到两行,如果去掉m修饰符

array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(12) "this is reg
"
  }
}

可见,即使加了m修饰符,也不是将整个字符串都匹配,这就是跨行与多行的区别。

另外,使用m模式匹配需要【注意】换行符是否真的有效。

<?php
$str1 = 'abc\nabcd';
$str2 = "abc\nabcd";
if(preg_match_all('#^abc#m', $str1, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

if(preg_match_all('#^abc#m', $str2, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

运行结果如下所示:

array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(3) "abc"
  }
}
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "abc"
    [1]=>
    string(3) "abc"
  }
}

运行可以看到,由于source1字符串使用单引号,\n作为普通字符而非换行符,因此匹配到的结果和预期不符。

3.点号通配模式(s)

点号通配模式的作用是使正则表达式里的点号元字符可以匹配换行符,如果没有这个修饰符,点号不匹配换行符。沿用上面的例子,如:

<?php
$str = "this is reg
Reg
this is
regexp turtor,oh reg";
if(preg_match_all('#this.*?reg#i', $str, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

运行结果为:

array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(11) "this is reg"
  }
}

“.”元字符表示除换行符以外的任意字符。所以按照这个推论,上述正则表达式应该能匹配到第一行,即“this is reg”,而第三行和第四行由于之间存在一个换行符,所以不能匹配。

如果给上述正则表达式加上s修饰符,那么匹配结果就不同了,如下所示:

<?php
$str = "this is reg
Reg
this is
regexp turtor,oh reg";
if(preg_match_all('#this.*?reg#is', $str, $arr)){
    var_dump($arr);
}else{
    echo "匹配不成功";
}

运行结果为:

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(11) "this is reg"
    [1]=>
    string(12) "this is
reg"
  }
}

可以看出,这个匹配跨行了。

我们只要牢记,s修饰符包括换行符。这个修饰符很有用,特别是在抓取一些文档时,由于存在不可见换行(这是很常见的),如果使用“.”匹配,就可能存在问题,这就需要表达式能匹配换行符。

<?php
$str = '<body>
<div class="content">
<div class="head"></div>
<div class="body"></div>
<div class="foot"></div>
</div>
</body>';
$array = array();
$array2 = array();
preg_match_all('#<body>(.*)<\/body>#', $str, $array);
var_dump($array);
preg_match_all('#<body>(.*)<\/body>#s', $str, $array2);
var_dump($array2);

运行结果为:

array(2) {
  [0]=>
  array(0) {
  }
  [1]=>
  array(0) {
  }
}
array(2) {
  [0]=>
  array(1) {
    [0]=>
    string(124) "<body>
<div class="content">
<div class="head"></div>
<div class="body"></div>
<div class="foot"></div>
</div>
</body>"
  }
  [1]=>
  array(1) {
    [0]=>
    string(111) "
<div class="content">
<div class="head"></div>
<div class="body"></div>
<div class="foot"></div>
</div>
"
  }
}

结果是第一个正则表达式没有匹配到任何内容,而第二个正则表达式匹配<body>标签之内的全部内容。原因在于,要匹配的文本在<body>标签后紧接着是一个不可见换行符,从而导致第一个正则表达式匹配失败。从这个例子中更能深刻体会到s修饰符的作用。

4.懒惰模式(U)

“U”相当于原来讲过的”?”,表示懒惰匹配。比如如下例子:

<?php
$str='[url]1.gif[/url][url]2.gif[/url][url]3.gif[/url]';
$s=preg_replace("#\[url\](.*)\[\/url\]#","<img src=http://www.test.com/upload/$1>",$str);
var_dump($s);

运行结果如下:

string(74) "<img src=http://www.test.com/upload/1.gif[/url][url]2.gif[/url][url]3.gif>"
<?php
$str='[url]1.gif[/url][url]2.gif[/url][url]3.gif[/url]';
$s=preg_replace("#\[url\](.*?)\[\/url\]#","<img src=http://www.test.com/upload/$1>",$str);
var_dump($s);

运行结果如下:

string(126) "<img src=http://www.test.com/upload/1.gif><img src=http://www.test.com/upload/2.gif><img src=http://www.test.com/upload/3.gif>"
<?php
$str='[url]1.gif[/url][url]2.gif[/url][url]3.gif[/url]';
$s=preg_replace("#\[url\](.*)\[\/url\]#U","<img src=http://www.test.com/upload/$1>",$str);
var_dump($s);

运行结果如下所示:

string(126) "<img src=http://www.test.com/upload/1.gif><img src=http://www.test.com/upload/2.gif><img src=http://www.test.com/upload/3.gif>"

由此可以看出:

#\[url\](.*)\[\/url\]#U

#\[url\](.*?)\[\/url\]#

这两个表达式是等价的。

5.结尾限制(D)

如果使用限制结尾字符,则不允许结尾有换行。例如,以下正则表达式将匹配“abc”、“abc\n”这样的字符,即忽视结尾的换行:

#abc$#

如果使用此模式,限定其不可有换行,必须以abc结尾,如下所示:

#abc$#D

6.支持UTF-8转义表达(u)

u修饰符启用PCRE中与Perl不兼容的额外功能,模式字符串被当成UTF-8。u修饰符在UNIX下自PHP 4.1.0起可用,在Win32下自PHP 4.2.3起可用,自PHP 4.3.5起开始检查模式的UTF-8合法性。看一个例子:

<?php
$str= 'php编程';
if (preg_match("#^[\x{4e00}-\x{9fa5}]+$#u",$str)) {
    echo "该字符串全部是中文";
} else {
    echo "该字符串不全是中文";
}

运行结果为:

该字符串全部是中文

正则表达式中使用了u修饰符,就可以使用UTF-8的转义表达,这实际上是兼容问题。在PHP中,使用此修饰符即可实现在表达式中支持UTF-8。


提示:除了上述几个模式修饰符之外,PHP里还支持另外几个修饰符,如A、x等,但不是很常用,这里就不做讲解了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值