博客
电影
宝箱
友链
关于
<
如何用正确的姿势写HTML
正则表达式实例解析
作者:
Cifer
类别: 技术
时间:2016-06-02 10:14:14
字数:6253
版权所有,未经允许,请勿转载,谢谢合作~
### 前言 正则表达式(regular expression)几乎在所有主流计算机语言中都有涉及,初学者很多时候都是从某些地方copy过来,如果不了解它,那也不知道copy的东西对不对。 它并不是一门语言,而是对字符串操作的一种逻辑公式,常常用regex表示。有趣的是,正则表达式并非计算机首创,而是源于数学科学家Stephen Kleene的《神经网事件的表示法》论文中, 再被引入Unix工具软件,自此广泛被利用,验证了理论先于实践。虽然不同的语言上会有一些流派的小差异,思想却是相同,为了方便表述,本处多以JavaScript为例。 正则就像翻译一样,同样的意思,有不同的翻译法,不同的高度。 PS:讲个小故事,有人以为只要英语足够牛逼,就可以成为牛逼的翻译官,too young too simple。电影《降临》七肢桶提供表意“武器”,这个可以翻译成知识,也可以成兵器,差别极大。比起外语能力,更重要的是知识深度与良知正义,所以翻译官就像语言学家一样,永无止境的东西。 正则表达式无非是实现两个功能,搜索与替换。博客内容来自[西法](http://www.boatsky.com "太空船博客" rel="nofollow")之前写的静态页,附带表达式工具:https://www.boatsky.com/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) 反向肯定预查 (?<!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.com.cn,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编译方式: <http://tool.lu/coderunner/>或 <http://www.shucunwang.com/RunCode/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); ```
如果觉得有帮忙,您可以在本页底部留言。
相关推荐:
从youtube观看记录分析时长
Webpack深入浅出plugin
Webpack自动更新php静态资源文件名hash
Webpack构建流程之源码分析
Webpack基于scss生成css独立文件
Webpack深入浅出loader
移动端浏览器真机调试的几种方法
接入台湾超商门店地址选择
ember入门教程
Ember之Handlebars模板引擎
Mac高频快捷键之前端篇
简述浏览器缓存之cookie
浏览器打开页面的过程中发生了什么
Git命令简化笔记
PHP实现微信JS-SDK权限验证
SQL快速运用指南
如何用正确的姿势写HTML
……
更多
<
如何用正确的姿势写HTML
全部留言
我要留言
内容:
网名:
邮箱:
个人网站:
发表
全部留言