zoukankan      html  css  js  c++  java
  • PHP Cookbook读书笔记 – 第22章正则表达式

    概述

    PHP提供了两组处理正则的函数,一组是传统的POSIX函数,都是以ereg开头(已过时,不推荐),另一组是Perl兼容的函数PCRE(Regular Expressions (Perl-Compatible)),函数名都是以preg作为前缀。包含的函数如下:

    元字符(meta-characters)

    \:将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。

    ^:匹配输入字符串的开始位置,在字符前表示否定如:[^A-Z]表示除A-Z之外的字符

    $:匹配输入字符串的结束位置

    .:匹配除换行符外的所有字符,如果希望包含换行符可以这样[.\n]

    [:匹配字符类别定义的开始位置

    ]:匹配字符类别定义的结束位置

    |:选择匹配

    (:子模式开始位置

    ):子模式结束位置

    ?:匹配前面的子表达式零次或一次。? 等价于 {0,1}

    *:匹配前面的子表达式零次或多次。*等价于{0,}

    +:匹配前面的子表达式一次或多次。+ 等价于 {1,}

    {:匹配最少/最多次数的开始位置

    }:匹配最少/最多次数的结束位置,{4,8}表示最少出现4次,最多8次

    -:指明字符的范围

    模式修饰符

    通常是放在模式定界符之后如:/pattern/i 中的i

    关键字 含义
    i 如果设置了此修饰符,模式中的字母大小写不敏感
    m 默认情况下,PCRE认为目标字符串由单行字符组成。如果设置了此修饰符,目标字符串多行时,模式匹配从目标字符开始位置到结束位置。
    s 前面介绍过模式中的点号(.)匹配除换行外的所有字符,如果设置了此修饰符,点号匹配所有字符,包含换行符。
    x 如果设置了此修饰符,模式中没有经过转义的或不在字符类型中的空白数据将被忽略。
    e 只对preg_replace()有效,在替换完成的结果作为eval函数的参数再运行一次
    A 约束匹配使其仅从目标字符串的开始位置搜索
    D 多行时美元符号仅匹配目标字符串的末尾,如果设置了m,则忽略此修饰符
    S 一个模式需要多次使用时,设定此修饰符会对模式进行分析从而提升匹配速度
    U ##使其量词默认为非贪婪,也可以通过在量词后以问号标记其非贪婪
    X ##反斜线后如果跟一个无意义的字母会报错,默认情况下会忽略
    J 修改本地PCRE_DUPNAMES,允许子组重名
    u ##模式字符串被认为是utf-8编码

    备注:标记为##的表示此方法与perl不兼容

    ereg与preg的区别

    1、preg模式不仅仅包含了字符串模式,同时也需要定界符。

    定界符可以是任何除数字、反斜线、空白外的任意字符,经常使用\或#作为定界符,例如

    //原
    ereg('pattern','string');
    //改为
    preg_match('/pattern/','string');//这里的分隔符是可以自定义的,可以将/pattern/改为@pattern@ 

    2、不要将定界符放在正则表达式的模式中,否则会导致模式提前结束。

    $ereg_pattern = '.+';
    $preg_pattern = addcslashes($ereg_pattern,'/'); 

    3、preg函数在不区分大小写时需要在结束定界符后加i

    //原
    eregi('pattern','string');
    //改为
    preg_match('/pattern/i','string');

    4、ereg_replace(参数1,参数2,参数3)中参数2如果是数字类型值,将被理解为ASCII编码值。preg_replace不存在这个问题,会将数字理解为数字

    字符匹配

    \b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'
    \B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'
    \d 匹配一个数字字符。等价于 [0-9]
    \D 匹配一个非数字字符。等价于 [^0-9]
    \f 匹配一个换页符。等价于 \x0c 和 \cL
    \n 匹配一个换行符。等价于 \x0a 和 \cJ
    \r 匹配一个回车符。等价于 \x0d 和 \cM
    \t 匹配一个制表符。等价于 \x09 和 \cI
    \v 匹配一个垂直制表符。等价于 \x0b 和 \cK
    \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
    \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
    \w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'
    \W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'
    \xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
    \num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
    \n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
    \nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
    \nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
    \un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)

    查找第N个匹配

    $todo = "
    first=Get Dressed
    next=Eat Jelly
    last=Squash every week into a day
    ";
    
    preg_match_all("/([a-zA-Z]+)=(.*)/", $todo, $matches, PREG_SET_ORDER);
    
    foreach ($matches as $match) {
        print "The {$match[1]} action is {$match[2]} \n";
    }

    贪婪or非贪婪匹配

    默认情况下,PHP都是贪婪匹配(最大化匹配),它会查找第一个起始标记和最后一个结束标记。

    非贪婪匹配(最小化匹配)通过模式修饰符U或者在元字符后面添加?来修改模式中一部分的匹配策略

    $html = 'I simply love your work';
    // 贪婪匹配
    $matchCount = preg_match_all('/.+/', $html, $matches);		//$matchCount = 1
    
    // 非贪婪匹配
    $matchCount = preg_match_all('/.+?/', $html, $matches);	//$matchCount = 2
    
    // 非贪婪匹配
    $matchCount = preg_match_all('/.+/U', $html, $matches);	//$matchCount = 2

    匹配HTML标签

    下面的例子是匹配HTML标签的,稍加改进可以用来匹配UBB标签

    $html = file_get_contents('example.html');
    preg_match_all('/<(strong|em)>(.+?)</\1>/is', $html, $matches);
    foreach ($matches[2] as $text) {
        print "Text: $text \n";
    }

    阻止对子模式匹配文本的捕获

    在子模式可选的情况下使用阻止捕获非常有用。可选的子模式可能会改变捕获的文本块数,通过 ?: 来设定其子模式不捕获

    $html = '
    
    ';
    
    preg_match_all('/rel="(?:prev|next)"(?: title="[^"]+?")? href=
    "([^"]*?)"/', $html, $linkMatches);
    
    print '$bothMatches is: '; var_dump($linkMatches);

    转义特殊字符

    如果是用户输入的字符串作为模式,需要转义,可以用preg_quote函数实现。例如:用户输入t.c时,不转义可能查到的结果包括tic、tucker等,转义后就是t.c

  • 相关阅读:
    61. 最长不含重复字符的子字符串
    60. 礼物的最大价值 (未理解)
    59. 把数字翻译成字符串
    58. 把数组排成最小的数
    57. 数字序列中某一位的数字 (不懂)
    spring data jpa 官方文档
    idea 编译报错 源发行版 1.8 需要目标发行版 1.8
    idea maven 依赖报错 invalid classes root
    solr
    spring boot 官方文档
  • 原文地址:https://www.cnblogs.com/Excellent/p/2254935.html
Copyright © 2011-2022 走看看