正则表达式教程二 —— 限定符和符号的运算优先级
2017-11-30 14:13 浏览(1448 更新于 2017-11-30 14:14

二、限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。

* 和 + 限定符是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个 ? 就可以实现最小匹配(非贪婪),后面会讲解。


1、*

匹配前面的子表达式零次或多次。

例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 

它会尽可能多的匹配内容,贪婪匹配


2、+

匹配前面的子表达式一次或多次。

例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 

它会尽可能多的匹配内容,贪婪匹配


3、?

匹配前面的子表达式零次或一次。

例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。 

它会尽可能少的匹配内容,非贪婪匹配

请看上一节的例子4

关于贪婪模式和非贪婪模式请看下面一个例子

例子 10

$s = <<<'TEXT'
<div>abc</div><div>def</div>
TEXT;

preg_match_all("#<div>(.+)</div>#",$s,$m);
print_r($m);
/*
Array
(
    [0] => Array
        (
            [0] => <div>abc</div><div>def</div>
        )

    [1] => Array
        (
            [0] => abc</div><div>def
        )
)
*/
preg_match_all("#<div>(.+?)</div>#",$s,$m);
print_r($m);
/*
Array
(
    [0] => Array
        (
            [0] => <div>abc</div>
            [1] => <div>def</div>
        )

    [1] => Array
        (
            [0] => abc
            [1] => def
        )
)
*/

匹配所有div标签包裹中的内容

第一个表达式匹配到了一个内容: abc</div><div>def,且还夹杂着 div ,肯定是不对的,因为 .+ 它是尽可能多的匹配内容(贪婪模式)

第二个表达式匹配到了两个内容(正好是我们想要的),abc 和 def ,因为 .+? 它是尽可能少的匹配内容(非贪婪模式)


4、{n}

n 是一个非负整数。匹配确定的 n 次。

例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 


5、{n,}

n 是一个非负整数。至少匹配n 次。

例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 


6、{n,m}

m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。


限定符还是很好理解的,例子也很浅显易懂


三、操作符的运算优先级


相同优先级的从左到右进行运算,不同优先级的运算先高后低

\

转义符


(), (?:), (?=), []

圆括号和方括号 ,(?:), (?=) 这两个组件后面会讲


*, +, ?, {n}, {n,}, {n,m}

限定符 


^, $

位置和顺序 


|

"或"操作 



例子 11 —— 匹配手机号码的例子

/*
这些号码段是我在网站找的最新的
中国联通号码:130、131、132、145(无线上网卡)、155、156、185(iPhone5上市后开放)、186、176(4G号段)、175(2015年9月10日正式启用,暂只对北京、上海和广东投放办理)
中国移动号码:134、135、136、137、138、139、147(无线上网卡)、150、151、152、157、158、159、182、183、187、188、178
中国电信号码:133、153、180、181、189、177、173、149
*/
$phone = '15111111111';
preg_match_all("#^(13\d|14[579]|15[012356789]|17[35678]|18[012356789])\d{8}$#",$phone,$m);
print_r($m);
/*
Array
(
    [0] => Array
        (
            [0] => 15111111111
        )

    [1] => Array
        (
            [0] => 151
        )

)
*/

\d 等价于 [0-9],等价于 [0123456789]

这里用的是严格的匹配方式,好处是能尽可能的验证手机号的真实性(并不能完全真实),坏处是,新增一个号码段就要改表达式

一个宽松的验证方式是: #^1[34578]\d{9}$# ,至于验证手机的真实性,就交给短信验证吧


布置一个练习题

待匹配内容

50010419930126203x


请写出验证此身份证的正则表达式

不用国家标准来验证,只验证长度和最后一位校验码,0-9或者是 x(这里暂定为小写)


评论(2)
发布评论
回复X
聊天室(0