PHP正则表达式小结

PHP正则表达式小结

感悟:

  2019年寒假到了,为了锻炼我们自己的编码能力,这个寒假准备利用php+html+css+mysql开发一个本地web小网站。在学习的过程中,我重新认识了一遍正则表达式,借用这个机会,将这次的认识记录起来,以免过段时间忘了一些细节。相对以前而言,我觉得这次对正则表达式的认识也有个十之七八了。


正文:

  简单的介绍一下谈诉我对正则表达式概念的理解,简单的说正则表达式有点像在描述一个或一类字符串的特征,这里的特征通常表现为一串或者一类具有共同特点的字符串(如果说这个特征是一段固定的字符串,它就类似于子串的概念),这个特征通常用来对其他的字符串进行匹配、查找、替换、分割等操作!正则表达式处理字符串的能力十分强大,但并不是所有处理字符串的操作都用到正则表达式,只有在对一些特别复杂的字符串进行操作的时候才会考虑是否使用正则表达式。

  在PHP中,正则表达式一般通过与三个特定的函数配合使用(preg_match()、preg_match_all()、preg_replace())。

简单介绍一下这三个函数的作用:

  1. preg_match():搜索subjectpattern给定的正则表达式的一个匹配。找到一次就停止。

    原型:

    1
    int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

    参数:

    • pattern:要搜索的模式(特征),字符串类型。
    • subject:被搜索的模板字符串。
    • matches:如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1]将包含第一个捕获子组匹配到的文本,以此类推。
    • flags:可以被设置为以下标记值:
      • PREG_OFFSET_CAPTURE如果传递了这个标记,对于每一个出现的匹配返回时会附加字符串偏移量(相对于目标字符串的)。 注意:这会改变填充到matches参数的数组,使其每个元素成为一个由 第0个元素是匹配到的字符串,第1个元素是该匹配字符串 在目标字符串subject中的偏移量。
    • offset:搜索从目标字符串的开始位置开始。可选参数 offset 用于 指定从目标字符串的某个位置开始搜索(单位是字节)。

    返回值:

    • 返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,在第一次匹配后 将会停止搜索。
  2. preg_match_all():搜索 subject 中所有匹配 pattern 给定正则表达式的匹配结果并且将它们以 flag 指定顺序输出到 matches 中。在第一个匹配找到后, 子序列继续从最后一次匹配位置搜索。

    原型:

    1
    int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )

    参数:

    • $pattern: 要搜索的模式,字符串形式。
    • $subject: 输入字符串。
    • $matches: 多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。
    • $flags:可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDERPREG_SET_ORDER):
      • PREG_PATTERN_ORDER: 结果排序为$matches[0]保存完整模式的所有匹配, $matches[1]保存第一个子组的所有匹配,以此类推。
      • PREG_SET_ORDER: 结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组), $matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。
      • PREG_OFFSET_CAPTURE: 如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。
    • offset: 通常, 查找时从目标字符串的开始位置开始。可选参数offset用于 从目标字符串中指定位置开始搜索(单位是字节)。

    返回值:

    • 返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。
  3. preg_replace():搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。

    原型:

    1
    mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

    参数:

    • $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
    • $replacement: 用于替换的字符串或字符串数组。
    • $subject: 要搜索替换的目标字符串或字符串数组。
    • $limit: 可选,对于每个模式用于每个$subject 字符串的最大可替换次数。 默认是-1(无限制)。
    • $count: 可选,为替换执行的次数。

    返回值:

    • 如果 subject 是一个数组, preg_replace() 返回一个数组, 其他情况下返回一个字符串。
    • 如果匹配被查找到,替换后的 subject 被返回,其他情况下 返回没有改变的 subject。如果发生错误,返回 NULL。

正则表达式:

下面选择用preg_match_all()配合正则表达式进行介绍操作字符串的过程。

  正则表达式的语法规则:由一个或多个普通字符或者元字符组成的一个字符串,由定界符/来表示正则表达式的开始和结束格式为/特征字符串/!此外,正则表达式还可以用除字母、数字和反斜线以外的字符作为定界符,例如#、!、{}、|等,但要保证始末位置的定界符一致。

  1. 普通字符:

    一般情况下指的都是26个英文字母(a到z)包括大小写、阿拉伯数字0-9、单引号和双引号。

    • 纯普通字符匹配举例:

    • 1
      2
      3
      4
      5
      6
      <?php
      $pattern='/test/';//此时的$pattern就是一个存储有正则表达式的变量
      $str="testTestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

    • 1
      2
      3
      4
      5
      6
      7
      8
      int(1) //preg_match_all的返回值,表示在字符串搜索到一次
      array(1) {//preg_match_all创建的数组,表示匹配到字符串的值和偏移量
      [0]=>
      array(1) {
      [0]=>
      string(4) "test"
      }
      }
  2. 元字符:

    能对正则表达式特征进行概括,代表某一类字符串,有特殊功能的字符(比如*、+、?等)。

    • 含元字符举例:

    • \d\D:前者表示任意十进制数(0-9)中的一个字符,后者表示除任意十进制数(0-9)外的其他字符中的一个字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <?php
      $pattern='/t\dst/';//\d匹配十进制数
      $str="t1stTestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      /*该结果成功,可匹配
      <?php
      $pattern='/t\Dst/';//\D匹配除十进制数外的一个字符
      $str="testTestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>*/

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(4) "t1st"
      }
      }
    • \s\S:前者表示任意空白字符(换页符、换行符、回车符、制表符、垂直制表符)中的一个字符,后者表示除空白字符(换页符、换行符、回车符、制表符、垂直制表符)外的其他字符中的一个字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <?php
      $pattern='/t\sst/';//\s匹配空白字符
      $str="t\nstTst\tstTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      /*该结果成功,可匹配
      <?php
      $pattern='/t\Sst/';//\S匹配除空白字符外的一个字符
      $str="testTestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>*/

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "t
      st"
      [1]=>
      string(4) "t st"
      }
      }
    • \w\W:前者表示任意数字或字母或下划线中的一个字符,后者表示除任意数字或字母或下划线外的其他字符中的一个字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <?php
      $pattern='/t\wst/';//\w匹配任意数字或字母或下划线
      $str="t_stTstastTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      /*该结果成功,可匹配
      <?php
      $pattern='/t\Wst/';//\W匹配除任意数字或字母或下划线外的一个字符
      $str="testTestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>*/

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "t_st"
      [1]=>
      string(4) "tast"
      }
      }
    • .:表示除换行符外的任意一个字符。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t.st/';//\d匹配除换行符外的任意一个字符
      $str="t_stTstastTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "t_st"
      [1]=>
      string(4) "tast"
      }
      }
    • *+*表示只含其前面第一个字符并连续重复0次,或1次,或多次的一串字符串;+表示只含其前面第一个字符并连续重复1次,或多次的一串字符串;表示只含其前面第一个字符并连续重复0次,或1次的一个字符。(注:重复0次就是任意代表任意一个字符,与其前面的第一个字符无关)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <?php
      $pattern='/te*st/';//*匹配只含其前面第一个字符并连续重复0次,或1次,或多次的一串字符串
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/te+st/';//+匹配只含其前面第一个字符并连续重复1次,或多次的一串字符串
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/te?st/';//?匹配只含其前面第一个字符并连续重复0次,或1次的一个字符
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      //*
      int(3)
      array(1) {
      [0]=>
      array(3) {
      [0]=>
      string(3) "tst"
      [1]=>
      string(4) "test"
      [2]=>
      string(7) "teeeest"
      }
      }
      //+
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "test"
      [1]=>
      string(7) "teeeest"
      }
      }
      //?
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(3) "tst"
      [1]=>
      string(4) "test"
      }
      }
    • {n}{n,}{n,m}{n}表示只含其前面第一个字符并正好连续出现n次的一串字符;{n,}表示只含其前面第一个字符并至少连续出现n次的一串字符;{n,m}表示只含其前面第一个字符并至少连续出现n次,至多出现m次的一串字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <?php
      $pattern='/te{0}st/';//{n}匹配只含其前面第一个字符并正好连续出现n次的一串字符
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/te{0,}st/';//{n,}匹配只含其前面第一个字符并至少连续出现n次的一串字符
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/te{0,2}st/';//{n,m}匹配十进制数
      $str="tsttestteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      //{n}
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(3) "tst"
      }
      }
      //{n,}
      int(3)
      array(1) {
      [0]=>
      array(3) {
      [0]=>
      string(3) "tst"
      [1]=>
      string(4) "test"
      [2]=>
      string(7) "teeeest"
      }
      }
      //{n/m}
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(3) "tst"
      [1]=>
      string(4) "test"
      }
      }
    • ^、\A$、\Z^\A表示其后第一个字符为字符串开始字符;$\Z表示其前第一个字符为字符串结束字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?php
      $pattern='/^test/';//^或\A匹配其后第一个字符为字符串开始字符
      $str="testteeeestTEXT";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/test$/';//$匹配其前第一个字符为字符串结束字符
      $str="teeeestTEXTtest";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      //上面两个代码结果一致
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(4) "test"
      }
      }
    • |:表示可以存在两个或多个正则表达式。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/test|TEXT/';//|表示可以存在两个或多个正则表达式
      $str="teeeestTEXTtest";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "TEXT"
      [1]=>
      string(4) "test"
      }
      }
    • [][^]:前者表示括号中存在的任意一个字符,后者表示除括号中存在的所有字符之外的任意一个字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?php
      $pattern='/t[abcde]st/';//[]匹配括号中存在的任意一个字符
      $str="testTEXTtast";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>
      <?php
      $pattern='/t[^abcde]st/';//[^]匹配除括号中存在的所有字符之外的任意一个字符
      $str="testTEXTt_st";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      //[]
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "test"
      [1]=>
      string(4) "tast"
      }
      }
      //[^]
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(4) "t_st"
      }
      }
    • ():表示将括弧中的字符串当作一个整体获取,一般配合\\n(n为阿拉伯数字,从1开始依次出现)使用,\\n表示前面匹配到的第n个括号里面的内容。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t(e)st\\1/';//()将括弧中的字符串当作一个整体获取
      $str="testeTEXTt_st";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      int(1)
      array(2) {
      [0]=>
      array(1) {
      [0]=>
      string(5) "teste"
      }
      [1]=>
      array(1) {
      [0]=>
      string(1) "e"
      }
      }
  3. 元组字符组合(常见)
    • .*.字符代表除换行符外的任意字符,*字符可代表一串同一个或多个字符组成的字符串。合起来便可以代表随机匹配到的一串由一个或多个未知字符组成的字符串,该组合会尽量匹配长的一串字符串,为贪婪匹配。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t.*t/';//.*匹配除换行符外的任意字符
      $str="testeTEXTt_st";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(13) "testeTEXTt_st"
      }
      }
    • .*?.字符代表除换行符外的任意字符,*字符可代表其前面的第一个字符,字符可代表其前面的第一个字符。合起来便是有限长的一个字符串(一次特征字符串),该组合在匹配尽量短的多个字符串,为懒惰匹配。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t.*?t/';//.*?匹配除换行符外的任意字符
      $str="testeTEXTt_st";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "test"
      [1]=>
      string(4) "t_st"
      }
      }
    • 等等等等

  4. 模式修正符(常见)

    模式修正符用在定界符后面,用于扩展正则表达式的功能(常见的有i、m、s、U)。

    • i:让正则表达式在匹配的时候不区分大小写

      举例:

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/test/i';//i让正则表达式在匹配的时候不区分大小写
      $str="testeTESTtEst";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      int(3)
      array(1) {
      [0]=>
      array(3) {
      [0]=>
      string(4) "test"
      [1]=>
      string(4) "TEST"
      [2]=>
      string(4) "tEst"
      }
      }
    • m:实现多行匹配,将一串含一个或多个\n符的字符串看成多串字符串处理。使用时必须满足两个条件:一是被搜索的字符串中必须含有\n符,二是正则表达式中必须有^$符。

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/^test/m';//m实现多行匹配
      $str="teste\ntEST\ntEst";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      int(1)
      array(1) {
      [0]=>
      array(1) {
      [0]=>
      string(4) "test"
      }
      }
    • s:可实现效果与m一样,该修正符专门与.元字符配合使用,因为有些情况下含.的正则表达式不接受\n符。简单的说,s修正符可以让.元字符匹配所有字符,包括换行符\n

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t.st/s';//s修正符可以让`.`元字符匹配所有字符,包括换行符\n
      $str="t\nste\ntEST\ntEst";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      int(2)
      array(1) {
      [0]=>
      array(2) {
      [0]=>
      string(4) "t
      st"
      [1]=>
      string(4) "tEst"
      }
      }
    • U:禁止贪婪匹配,等价于.*?

      1
      2
      3
      4
      5
      6
      <?php
      $pattern='/t.*t/U';//\d匹配十进制数
      $str="tesstetESt\ntEst";//该字符串为被搜索的字符串
      var_dump(preg_match_all($pattern, $str, $arr));
      var_dump($arr);
      ?>

      结果:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      int(3)
      array(1) {
      [0]=>
      array(3) {
      [0]=>
      string(5) "tesst"
      [1]=>
      string(4) "tESt"
      [2]=>
      string(4) "tEst"
      }
      }

      模式修正符可以搭配使用,搭配效果是修正符功能的交集。如Ui是不区分大小写下禁止贪婪匹配。


总结

  以上内容就是我在本次学习中理解到的正则表达式。正则表达式不是php的产物,在其他语言中也有相同的功能。这里用的是php解释,如果有什么说的不正确或者不足,希望大牛们能提出批评。这是小弟的QQ:2790169047,谢谢大牛。

参考文献:

http://www.runoob.com/php/

http://www.php.net/manual/zh/function.preg-match.php

http://edu.51cto.com/course/1676.html