正则表达式实例解析
类别: 技术
时间:-06-02 10:14:14
字数:6253
版权所有,未经允许,请勿转载,谢谢合作~
### 前言
正则表达式(regular expression)几乎在所有主流计算机语言中都有涉及,初学者很多时候都是从某些地方copy过来,如果不了解它,那也不知道copy的东西对不对。
它并不是一门语言,而是对字符串操作的一种逻辑公式,常常用regex表示。有趣的是,正则表达式并非计算机首创,而是源于数学科学家Stephen Kleene的《神经网事件的表示法》论文中, 再被引入Unix工具软件,自此广泛被利用,验证了理论先于实践。虽然不同的语言上会有一些流派的小差异,思想却是相同,为了方便表述,本处多以JavaScript为例。
正则就像翻译一样,同样的意思,有不同的翻译法,不同的高度。
PS:讲个小故事,有人以为只要英语足够牛逼,就可以成为牛逼的翻译官,too young too simple。电影《降临》七肢桶提供表意“武器”,这个可以翻译成知识,也可以成兵器,差别极大。比起外语能力,更重要的是知识深度与良知正义,所以翻译官就像语言学家一样,永无止境的东西。
正则表达式无非是实现两个功能,搜索与替换。博客内容来自[西法]( "太空船博客" rel="nofollow")之前写的静态页,附带表达式工具:/static/tools/regexp/regexp.html
### 常用语法
^字符串开始位置
$字符串结束位置
\转义字符
\d数字
\D非数字
\w任何单词字符,包括字母数字下划线
\W非单词字符
\s不可见字符
\S可见字符
+匹配表达式1次以上
星号,匹配表达式任意次,尽量使用*?这种非贪婪的模式
?匹配表达式1次或0次
{n}匹配表达式n次,n非负
{n,m}匹配表达式n次至m次,n<=m
[abcde]匹配字符集任意一个,等价于[a-e]
[^0-9]匹配不在本字符集任意一个,等价于\D
(x|y|z)匹配字符集任意一个,等价于[xyz]
\b 单词边界
\B 非单词边界
以下为非获取匹配子表达式
(?:pattern) 匹配pattern但不获取匹配结果,不进行存储供以后使用
(?=pattern) 正向肯定预查
(?!pattern) 正向否定预查
(?<=pattern) 反向肯定预查
(?
### 简单实例
#### QQ号
分析:QQ号是纯数字,4位至10位,不过也有把11位手机号当QQ的情况
正则:
```
/^[1-9]\d{3,10}$/
```
#### 手机号码
分析:
移动号19:134,135,136,137,138,139,147,150,151,152,157,158,159,178,182,183,184,187,188
联通号09:130,131,132,155,156,185,186,145,170,171,176
电信号06:133,153,177,180,181,189
综合:
130,131,132,133,134,135,136,137,138,139
145,147
150,151,152,153,155,156,157,158,159
170,171,176,177,178
180,181,182,183,184,185,186,187,188,189
正则:
```
/^(13|14|15|17|18)[0-9]{9}$/
```
#### 数字
js中,如果想验证整数n,可以直接用Number.isInteger(n)。
如果要验证n是否是数字,我们一般是使用:
Object.prototype.toString.call(n) === '[object Number]'
这存在几个明显的问题:
其一:如果n是一个数字,传输中是以String来传的,这时有问题
其二:如果n为NaN,也认为是数字,这可能不是我们想要的
其三:JS数字范围有限,如果超过了JS数字的范围1.797693134862316e+308,n变成了Infinity,这时上式也成立,我们并不想认为Infinity是数字。
其四:我们可能只想要一个验证长是不是数字,比如有个极大的数,超出了JS数的范围,不应该认为这个极大的数就不是数,只是原生JS不支持而已。
为了解决这些问题,用正则匹配。
我们把数分成整数、小数、指数,其中整数部分与指数数字是带正负的
整数 [\+\-]?\d*
小数部分 \.\d+
指数 e[\+\-]?\d*
最终
```
/^[\+\-]?\d*(\.\d+)?(e[\+\-]?\d*)?$/
```
#### 邮箱
分析:邮箱的格式一直是一个有争议的问题,最常见的格式如xx@xx.xx,不过像xx.oo@,xx_xx-xx+xx.xx@xx-xx.xx也能见到。
不过多数邮箱还是会在做出类似以下的限定:
1.邮箱只能包含字母数字.-_+与一个@,@之前必须有字母或数字,@之后必须要"2级域名"."1级域名"
2.开头必须是字母或数字,不能有连续的.-_
3.一级域名一般是只包含字母
正则:
```
/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.[a-zA-Z]+$/
```
#### 网址
分析:网址正则几乎随处可见,前缀是传输协议,如http,https,ftp,sftp,rtsp(实时流传输协议),mms(串流媒体传送协议),magnet(BT种子)等等,接着则是三级域名(有可能省略),二级域名,一级域名,当然也可能只是IP址,最后详细路径
本处,以本网为例
正则:
```
/^http(s?):\/\/((\w)+\.)?boatsky\.com(\.cn)?(\/|$)/i
```
#### 日期时间
分析:日期时间格式 多样,为了便于表示,以传统日期年月日时分秒,格式xxxx/xx/xx xx:xx:xx为例,其中年份为4位数,所有位数不足都须补0
首先,我要要验证这个输入是否像一个日期,并不考虑这个日期是否存在
日期+时间格式正则:
```
/^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])(\x20)(2[0-3]|[0-1][0-9]):([0-5]\d):[0-5]\d$/
```
分析:如果加上1,3,5,7,8,10,12月有31天,4,6,9,11有30天,2月有28天(假设都是平年)
平年月份的正则:
```
/02\/(0[1-9]|1[0-9]|2[0-8])|(0[469]|11)\/(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01])/
```
所以平年的正则:
```
/^\d{4}\/((02\/(0[1-9]|1[0-9]|2[0-8])|(0[469]|11)\/(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01])))(\x20)(2[0-3]|[0-1][0-9]):([0-5]\d):[0-5]\d$/
```
再加上闰年(能被4整除,若能被100整除则需要再被400整除,就是所谓的“4年一闰,100年不闰,400年再闰”),闰年2月29天,平年2月28天
闰年2月有29天也就是两种情况:
1.能被4整除且不能被100整除。什么样的数能被4整除?因为100能被4整除,所以只要保证后两位数能被4整除就行了,即“个位为048,十位为偶数”或“个位为26,十位为奇数”,加上个位与十位不能同时为0,如下:
```
/\d{2}([2468][048]|[13579][26]|0[48])/
```
2.能被400整除。千位与百位需要被4整除,(没有公元0年,只有公元前1年与公元1年)
```
/([2468][048]|[13579][26]|0[48])00/
```
所以闰年的正则:
```
/\d{2}([2468][048]|[13579][26]|0[48])|([2468][048]|[13579][26]|0[48])00/
```
综上,最终结果:
```
/^((\d{4}\/((02\/(0[1-9]|1[0-9]|2[0-8])|(0[469]|11)\/(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01]))))|((\d{2}([2468][048]|[13579][26]|0[48])|([2468][048]|[13579][26]|0[48])00)\/(02\/(0[1-9]|1[0-9]|2[0-9])|(0[469]|11)\/(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01]))))(\x20)(2[0-3]|[0-1][0-9]):([0-5]\d):[0-5]\d$/
```
#### 密码复杂度
分析:现在很多网站都流行对用户的密码进行安全等级评定,提醒用户设置更复杂的密码,更大可能的保护账户安全。
其实所谓的复杂度,无非就是用多个正则进行配置,匹配上越多的正则,则复杂度越高
本处对密码设以下规则,长度8-32,建议包括大写字母,建议包括小写字母,建议包括数字,建议包括特殊字符,不建议包括三个连续字符,
### JavaScript中简单使用
在JS中,正则表达式用RegExp对象表示,可以用RegExp(pattern,attributes)构造函数来创建RegExp对象,其第一个参数pattern是上述的正则表示式,第二个参数是修饰符,g(全局匹配),i(不区分大小写匹配),m(多行匹配)
```javascript
var regExp = new RegExp("/^(13|14|15|17|18)[0-9]{9}$/");
```
也可以特殊的直接量语法创建:
```javascript
var regExp = /^(13|14|15|17|18)[0-9]{9}$/;
```
RegExp包括以下方法:
complie:编译正则,增快速度
test:检索字符串指定值
```javascript
var regExp = new RegExp(/^(13|14|15|17|18)[0-9]{9}$/);
var result = regExp.test("18812345678"); //返回true或false,这里是true
```
exec:检索字符串指定值,并确定位置,如果搜索修饰符不是g,那么返回值第0个是匹配上的字符串还包括index(匹配文本第一个的位置)与input(当前被匹配的字符串)两个属性
```javascript
var regExp = new RegExp(regExpValuePattern);
var checkResult = regExp.exec(checkContentValue);
if(checkResult){
printResult = "位置:" + checkResult.index + ",字符:" + checkResult[0];
}
var regExp = new RegExp(/a/,g);
var result;
while((result == regExp.exec("abcdefabdaafg"))){
console.log(result);
console.log(regExp.lastIndex);
}
```
String对象有search,match,replace,split是支持正则表达式的
比如用replace把一个正整数转成千位用,分隔
```javascript
function numberFormat(num) {
if(!(Object.prototype.toString.call(1) === '[object Number]' && Math.floor(num) === num)){
return num;
}
let reg=/\d{1,3}(?=(\d{3})+$)/g;
return (num + '').replace(reg, '$&,');
}
```
### PHP中简单使用
如果懒的装PHP,则可以使用在线的PHP编译方式:
或
preg_match("$regex",$byMatchStr),其中$regex为正则表达式,$byMatchStr为被匹配的字符串,成功返回true,否则false:
```php
if(preg_match("/php/", "php is best language of the world. php is not pai huang pian.", $matches)){
echo "php was found:". $matches[0];
} else {
echo "php was not found:";
}
```
preg_match_all("$regex",$byMatchStr),其中$regex为正则表达式,$byMatchStr为被匹配的字符串,成功返回true,否则false:
```php
if(preg_match_all("/php/", "php is best language of the world. php is not pai huang pian.", $matches)){
echo "php was found:"
var_dump($matches); } else {
echo "php was not found:";
}
```
preg_replace("$regex",$str,$byMatchStr),其中$str把$byMatchStr替换掉的字符串:
```php
$byMatchStr = "php is best language of the world.";
echo $byMatchStr;
echo "\n";
echo preg_replace("/php/","JavaScript",$byMatchStr);
echo "\n";
echo $byMatchStr;
```
preg_split("$regex",$byMatchStr),使用正则转换数组:
```php
$byMatchStr = "php is best language of the world.";
$array = preg_split("/ /",$byMatchStr);
foreach($array as $a){
echo $a."\n";
}
```
preg_grep("$regex",$byMatchArray),使用正则替换数组,生成新数组:
```php
$byMatchArray = array("a","b","c","ab","ba","bc");
$newArray = preg_grep("/b$/",$byMatchArray);
var_dump($newArray);
```
全部留言
我要留言
内容:
网名:
邮箱:
个人网站:
发表