正则表达式

正则表达式被用来检索或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如:JavaScript、PHP、ASP、JAVA、Perl、C#、NET、ColdFusion、Python、Visual Basic、MySQL、Linux、Vi编辑器等等语言都支持正则表达式。

简单来说正则表达式就是完成字符串的增、删、改、查。

定界符

正则表达式语句需要由分隔符(定界符)闭合包裹,分隔符可以是任意非字母数字、非反斜线、非空白字符。

经常使用的分隔符是正斜线(/),hash符号(#)以及取反符号(~)。
建议使用 // 作为定界符,因为与 js 一致。

  1. $status = preg_match('/0x208/', '0x208.cc');
  2. var_dump($status);

元字符

元字符是正则表达式中的最小元素,只代表单一(一个)字符。下面是元字符列表。

元字符 说明 范围
\d 匹配任意一个数字 [0-9]
\D 匹配除了数字以外的任意一个字符 [^0-9]
\w 匹配任意一个英文字母、数字或下划线 [a-zA-Z_0-9]
\W 匹配除了英文字母、数字或下划线以外的任意字符 [^a-zA-Z_0-9]
\s 匹配任意一个空白字符 [\n\f\r\t\v]
\S 匹配除了空白符以外的任意一个字符 [^\n\f\r\t\v]
\n 匹配换行字符
\t 制表符
  1. var_dump(preg_match('/\d/', '1'));
  2. var_dump(preg_match('/\D/', 'h'));
  3. var_dump(preg_match('/\w/', '_'));
  4. var_dump(preg_match('/\W/', '@'));
  5. var_dump(preg_match('/\s/', ' '));
  6. var_dump(preg_match('/\S/', 'h'));
  7. var_dump(preg_match('/\n/', "\n"));
  8. var_dump(preg_match('/\n/', '
  9. '));
  10. var_dump(preg_match('/\t/', "\t"));

元字符表(原子表)

在一组字符中匹配某个字符,在正则表达式中通过原子表来完成,就是放到方括号中。

原子表 说明
[] 只匹配其中的一个原子
[^] 只匹配”除了”其中字符的任意一个原子
[0-9] 匹配0-9任意一个数字
[a-z] 匹配小写a-z任意一个字母
[A-Z] 匹配大写A-Z任意一个字母
. 点在正则中表示除换行符外的任意字符

匹配了 678 外的任何字符

  1. $status = preg_match('/[^678]/', 678);
  2. var_dump($status);

匹配大小写字母

  1. $status = preg_match('/[a-zA-Z]/', 'a');
  2. var_dump($status);

. 匹配字符

  1. $status = preg_match('/./', 'laot');
  2. var_dump($status);

下面是通过原子表拆分字符串

  1. $str ="1.jpg@2.jpg@3.jpg#4.jpg";
  2. $arr = preg_split('/[@#]/',$str); //按正则表达式拆分字符串
  3. print_r($arr); //输出结果 Array ( [0] => 1.jpg [1] => 2.jpg [2] => 3.jpg [3] => 4.jpg )

原子组

  • 如果一次要匹配多个原子,可以通过原子组完成
  • 原子组与原子表的查别在于原子组一次匹配多个原子,而原子表则是匹配成功表中的一个原子就可以。
  • 原子组用 () 表示

下面是使用正则表达式将 0x208.cc 字符串中的 0x208 描红。

  1. $str = "官网0x208.cc 论坛0x208.cc,我在网名叫laot";
  2. $preg = "/(0x208)\.cc/is";
  3. $newStr= preg_replace($preg, '<span style="color:#f00">\1</span>.cc', $str);
  4. echo $newStr;

匹配字符边界

如果向匹配字符的边界,边界包括空格、标点符号、换行等,可以使用正则表达式的匹配字符边界修饰符如下。

符号 说明
^ 匹配字符串的开始
$ 匹配字符串的结束,忽略换行符
  1. $status = preg_match('/^laot$/', 'laot');
  2. var_dump($status); //返回真

选择修饰符

| 这个符号代表选择修饰符,也就是 | 左右两则有一个匹配到就可以。
下面是通过选择修饰符将域名修改为 aaaa

  1. $str = "http://www.baidu.com与新浪网http://www.sina.com";
  2. $preg = "/\.(baidu|sina)\./is";
  3. echo preg_replace($preg, '.aaaa.', $str);

匹配域名后缀

  1. $str = '来了,老弟!有问题就上 0x208.cc 我们在那里等你';
  2. $preg = '/(0x208|aaaa)\.cc/';
  3. $replace = '<a href="http://www.\1.cc">\1.cc</a>';
  4. echo preg_replace($preg, $replace, $str);

重复匹配

如果要重复匹配一些内容时我们要使用重复匹配修饰符,包括以下几种。

因为正则最小单位是原子,而我们很少只匹配一个原子如a、b所以基本上重复匹配在每条正则语句中都是比用到的内容。

符号 说明
* 重复0次或多次
+ 重复一次或多次
? 重复0次或1次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
  1. var_dump(preg_match('/^.*$/', '')); //* 零个及空字符串也是可以的
  2. var_dump(preg_match('/^[0-9]+$/', '1976')); // 返回真
  3. var_dump(preg_match('/^9?$/', '99')); // 返回假
  4. var_dump(preg_match('/^9{2}$/', '99')); // 返回真
  5. var_dump(preg_match('/^[0-9]{2,}$/', '123')); //返回真
  6. var_dump(preg_match('/^[0-9]{2,3}$/', '1234')); // 返回假,只能2~3位

下面匹配域名操作

  1. $web = 'sina.com';
  2. var_dump(preg_match('/^[a-z-0-9-]+\.(com|net|com\.cn|org|cn)$/', $web));

下面是把 h1 标签内容加上超链接

  1. $str = <<<html
  2. <h1>hello laot</h1>
  3. html;
  4. echo preg_replace('/<h1>(.+)<\/h1>/', '<a href="http://0x208.cc">\1</a>', $str);

禁止重复匹配(贪婪模式)

正则表达式在进行重复匹配时,默认是贪婪模式匹配,也就是说会尽量匹配更多内容,但是有的时候我们并不希望他匹配更多内容,这时可以通过 ? 进行修饰来关闭贪婪模式。

符号 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
  1. $str = '123456';
  2. preg_match('/\d+?/',$str,$matches);
  3. print_r($matches);

因为增加了 ? 所以只匹配数字1
下面是使用禁止贪婪符替换将h1标签内容倾斜处理

  1. $str = "<h1>你好</h1><h1>laot</h1>";
  2. $preg = '/<h1>(.*?)<\/h1>/';
  3. $replace = '<h1><em>\1</em></h1>';
  4. echo preg_replace($preg,$replace,$str);

下面是替换h1-h6标签内容,就不需要使用禁止贪婪符了

  1. $str = "<h1>你好</h1><h2>laot</h2>";
  2. $preg = '/<h([1-6])>(.*)<\/h\1>/';
  3. $replace = '<h\1><em>\2</em></h\1>';
  4. echo preg_replace($preg,$replace,$str);

模式修正符

正则表达式在执行时会按他们的默认执行方式进行,但有时候默认的处理方式不能总满足我们的需求,所以可以使用模式修正符更改默认方式。

符号 说明
i 不区分大小写字母匹配
s 将字符串视为单行,换行符做普通字符看代,使”.”匹配任何字符
x 忽略空白和#符号,根据此特性可以添加正则注释
m ^与$匹配按行匹配
U 与?功能相似,禁止贪婪匹配
A 强制从字符串开始匹配(多行时默认以每行开始设置)
D 以$结尾时不允许后面有换行(使用m时无效)

i修正符不匹配大小写示例

  1. $str = 'http://Baidu.Com laot';
  2. $preg = '/http:\/\/baidu.com/i';
  3. $replace= '<a href="\0">\0</a>';
  4. echo preg_replace($preg,$replace,$str);

s将字符串表示为单行操作

  1. $preg = '#(<h1>)(.*?)(</h1>)#s';
  2. preg_match_all($preg,$str,$matches);
  3. //print_r($matches);
  4. $replace = '\1<span style="color:red">\2\3';
  5. echo preg_replace($preg,$replace,$str);

m使用^与$按单行操作文本

  1. $str = <<<php
  2. #1 2022-02-12
  3. laot
  4. @#100
  5. 雅虎网
  6. #2 2033-09-11
  7. 0x208
  8. php;
  9. $preg = '/^#\d+.*[\r|\n]$/m';
  10. preg_match_all($preg, $str, $matches);
  11. print_r($matches);

x字符忽略空白和添加正则注释

  1. 添加注释

    1. $str='0x208.cc';
    2. $preg = '/^0
    3. # 这是匹配以 0 开始的内容
    4. /x';
    5. echo preg_replace($preg,'',$str);
  2. 当设置了/x后 # 会被忽略,如果正则中使用#需要转义处理

    1. $str=<<<php
    2. #1
    3. laot#1
    4. #2asd
    5. 哈哈#2
    6. php;
    7. $preg = '/^
    8. \#\d #匹配以#数字开始
    9. +.* $ #后跟任何字符
    10. /mx';
    11. echo preg_replace($preg,'',$str);

    U 禁止贪婪匹配

    1. $str = <<<php
    2. <h1>laot</h1>
    3. <h1>0x208</h1>
    4. php;
    5. ;
    6. $preg = '#<h1>.*</h1>#sU';
    7. preg_match_all($preg,$str,$matches);
    8. print_r($matches);

    A 与^限定符使用效果先死,必须以目标字符串开始。下面是验证邮箱例子

    1. $str = '1477821088@qq.com';
    2. $preg = '/\w+@[\w\.]+/A';
    3. preg_match_all($preg,$str,$matches);
    4. print_r($matches);

    D修正符使用不允许以换行符结束

    1. $str = <<<php
    2. 3a\n
    3. php;
    4. $preg = '/\d+a$/D';
    5. preg_match_all($preg,$str,$matches);
    6. print_r($matches);

常用函数

preg_match

获取第一个匹配的内容

  1. $str= '1@2@3';
  2. preg_match('/\d+/',$str,$matches);
  3. print_r($matches);

preg_match_all

获取所有匹配的内容

  1. $str= '1@2@3';
  2. preg_match_all('/\d+/',$str,$matches);
  3. print_r($matches);

preg_split

通过正则表达式拆分字符串

  1. $str= '1@2#3';
  2. $arr = preg_split('/@|#/',$str);
  3. print_r($arr);

preg_replace

通过正则表达式替换

  1. $str= '1@2#3';
  2. echo preg_replace('/@|#/','-',$str);

preg_replace_callback

使用回调函数进行替换操作

  1. $str = '1@2@3';
  2. echo preg_replace_callback('/\d+/',function ($matches) {
  3. return $matches[0]+100;
  4. }, $str);