有趣的正则表达式

目录

正则表达中有许多的知识点,做成目录的形式方便日后查找。本文举的例子皆为php,php中的正则表达式,有preg_match($pattern, $str, $matches)和preg_match_all(…)两种 ,前者匹配成功一次就返回结果,后者是全局的正则匹配,会将所有成立的字符串存入到$matches中,两者都会返回匹配的次数。

两个基本原则

  1. 最左原则 ,正则匹配都是从字符串最左边开始的;
  2. 最长原则 ,正则匹配会匹配出符合要求的最长的字符串(贪婪模式);

定界符

一般我们使用’/’或者’#’作为定界符,但在url中带有很多的’/’,这时我们使用’#’更好
举例:

<?php
$pattern = '/http:\/\/.*com/';
$str = 'http://baidu.com';
preg_match($pattern, $str, $matches);
var_dump($matches);
?>

result:
  array(1) {
  [0]=>
  string(16) "http://baidu.com"
}

使用’#’作为定界符

<?php
$pattern = '#http://.*com#';
$str = 'http://baidu.com';
preg_match($pattern, $str, $matches);
var_dump($matches);
?>

result:
  array(1) {
  [0]=>
  string(16) "http://baidu.com"
}

修饰符

用于改变正则表达式的行为
i 就是一个修饰符,作用是忽略大小写;x也是修饰符,其作用是忽略空格

<?php
$pattern = '#http://.*com#i';
$str = 'http://www.youku.Com/show_page/CDE.html';
preg_match($pattern, $str, $matches);
var_dump($matches);
?>

result:
array(1) {
  [0]=>
  string(20) "http://www.youku.Com"
}

字符域

符号 含义
\d 表示匹配一个数字字符,等价于 [0-9]
\D 匹配一个非数字字符,等价于[^0-9]
\f 匹配一个换页符
\n 匹配一个换行符,等价于\x0a和\cJ
\r 匹配一个回车符,等价于\x0d和\cM
\s 匹配任何空白字符 空格tab换页符等 等价于[\f\n\r\t\v]
\S 匹配任何非空白字符
\t 匹配任何一个制表符 等价于\x09和\cI
\v 匹配一个垂直制表符 等价于\x0b和\cK
\w 匹配包括下划线的任何单个字符 等价于[A-Za-z0-9_]
\W 匹配任何非单次字符

限定符

跟在字符域后的符号,例如:
\d{n,m} 表示匹配n到m个数字
\d{i} 这是[\d]{i,i}的简写,指定匹配i次
\d{n,} 表示匹配超过n个数字

脱字符

符号 含义
* [\w]* 表示匹配0到多个包括下划线的字符
+ [\D]+ 表示匹配1到多个非数字的字符
^ 放在表达式之前,表示用字符串起始位置匹配
$ 表示匹配字符串的末尾
[] 方括号表示只要匹配方括号任何元素成立即可,在[]中 ^表示取反可以直接使用[.],不需要对.进行转义,如[\d.]表示匹配数字或 .
? 表示匹配子表达式一次或零次:he(llo)? 可以匹配he 也可以匹配hello
. 表示匹配除换行符外的任何单个字符; (.|\n)即可匹配任何字符
() 正则中的小括号很有意思,我一开始以为就是单纯地把多个表达式组合在一起而已。举个栗子,’(abc)’表示匹配字符串abc,但()还有个额外操作,就是将括号里的内容加入到匹配数组$matches中。

备注
'\'作为转义字符,如果要匹配‘\’,则应该这么写:

$pattern = "#\\\#";        //连续三个\才可以

'^'的例子:

<?php
$pattern = '#^http://.*com#i';
$str = 'http://www.youku.Com/show_page/CDE.html';
preg_match($pattern, $str, $matches);
var_dump($matches);
?>

表示$str的起始位置是否满足正则匹配

'[]'的例子:

<?php
$str = "absjd";
$p = '/[abc]/';
preg_match($p,$str,$matches);
var_dump($matches);
?>
结果:
array(1) {
  [0]=>
  string(1) "a"
}

关于?,我还出了一次糗,网上有人用这样一个正则表达式解析网页内容:
‘/\[baidu\][\s\S]*?\[\/baidu\]/’ 可以匹配诸如’[baidu]abcde[/baidu]’这样的内容
我在想*已经表示匹配0到多次了,?表示匹配0或1次,这不是画蛇添足吗,实际上,这里的?还有一种作用,叫做非贪婪符号,默认会得到符合要求的最长字符串,非贪婪符号则是得到符合要求的最短字符串。

关于’()'例子:

<?php
$str = "abcdef";
$p = '/(abc)d/';
preg_match($p,$str,$matches);
var_dump($matches);
?>
结果:
array(2) {
  [0]=>
  string(4) "abcd"
  [1]=>
  string(3) "abc"
}

若不想把()中内容加入到匹配数组,可以使用’(?:)’
例子:

<?php
$str = "abcdef";
$p = '/(?:abc)d/';
preg_match($p,$str,$matches);
var_dump($matches);
?>
结果:
array(1) {
  [0]=>
  string(4) "abcd"
}

通配符

符号 含义
正向预查 (?=) 表示匹配字符的右边 对应的否定形式(?!)
反向预查 (?<=) 对应的否定形式(?<!) 表示匹配字符的左边

举例:
表示匹配的字符’bc’,左边需要是字符’a’,右边需要是字符’d’

  <?php
    $pattern = '#(?<=a)bc(?=d)#';
    $str = 'abcdef';
    preg_match($pattern, $str, $matches);
    var_dump($matches);
    ?>

另外,需要注意,正向预查和反向预查符都是不占字符宽度的
栗子:

<?php
$pattern1 = '#(?<=a)bc(?=d)e#';
$pattern2 = '#(?<=a)bc(?=d)de#';
$str = 'abcdef';
preg_match($pattern1, $str, $matches1);
var_dump("matches1:");
var_dump($matches1);
preg_match($pattern2, $str, $matches2);
var_dump("matches2:");
var_dump($matches2);
?>

result:
string(9) "matches1:"
array(0) {
}

string(9) "matches2:"
array(1) {
  [0]=>
  string(4) "bcde"
}

一些常用的正则匹配式

用正则匹配ip

  1. 我一开始写了 '/^\d+\.\d+\.\d+\.\d+$/' (’.’是脱字符,需要进行转义)起始是大于等于一位的数字. 大于等于一位的数字. 大于等于一位的数字. 大于等于一位的数字为结尾
    进一步用’()’优化:'/^(?:\d+\.){3}\d+$/';
  2. 看到网上有人会这么写 '/^(?<!\.)[\d.]+(?!\.)$/' 起始是大于等于一位的数字,接下来是’.’或者数字都无所谓,只要结尾是数字就能完成匹配,这其实很不严谨。
  3. 我的写法1还是存在问题,并没有很好地限制数字长度和大小,要知道ip中数字是小于等于255的
    我用上限定符对数字做一个限制:'/2([0-4]\d|5[0-5])|1?\d{1,2}/'
    最终纯净版:
    '/^(?:(?:2(?:[0-4]\d|5[0-5])|1?\d{1,2})\.){3}(?:2(?:[0-4]\d|5[0-5])|1?\d{1,2})$/'
    不纯净版(若只取匹配数组的第一个元素则和纯净版一样):
    '/^((2([0-4]\d|5[0-5])|1?\d{1,2})\.){3}(2([0-4]\d|5[0-5])|1?\d{1,2})$/'

用正则匹配手机号

手机号的正则简单的多了:'/^1[34578]\d{9}$/'

用正则匹配用户名

用户名一般为字母下划线开头,由字母数字下划线组成(可以用到\w)

 '/^[A-Za-z_]\w+$/'

用正则匹配邮箱号

邮箱一般是邮箱名@域名;
邮箱名由字母数字下划线中划线组成,因此可以用[\w-]+表示
域名的规律一般为[四级域名].[三级域名].[二级域名].[一级域名]
我的写法:

'/^[\w-]+(\.[\w-]+)*@[\w-]+(.[a-z]{2,})+$/i'

这个正则式能过滤很多错误邮箱号,但邮箱的写法太多,这个正则式并不完美。
菜鸟上写的邮箱正则式是这样的:

'/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/'

其实写的和我的差不多,大家可以做一个参考。

用正则匹配密码

这里的密码比较简单,包含数字、大小写字母、和一些常用的符号,视具体需求进行修改

'/^[a-zA-Z0-9_.!@#$%^&*]{6,}$/'

JS中使用正则表达式的方法

var pattern = /^[a-zA-Z0-9_.!@#$%^&*]{6,}$/;
if (!pattern.test(password)){
	alert("密码不规范");
}

猜你喜欢

转载自blog.csdn.net/qq_39985298/article/details/88819546