jQuery源码分析-02正则表达式 RegExp 常用正则表达式


Posted in Javascript onNovember 14, 2011

作者:nuysoft/JS攻城师/高云 QQ:47214707 EMail:nuysoft@gmail.com
声明:本文为原创文章,如需转载,请注明来源并保留原文链接。
后文预告:jQuery中的正则表达式分析

2.4 常用正则表达式
在网上找到一篇广为流传的文章《常用正则表达式》,逐一分析,不足地方进行补充和纠正。

常用的数字正则(严格匹配) 
正则 含义 
^[1-9]\d*$ 匹配正整数 
^-[1-9]\d*$ 匹配负整数 
^-?[1-9]\d*$ 匹配整数 
^[1-9]\d*|0$ 匹配非负整数(正整数 + 0) 
^-[1-9]\d*|0$ 匹配非正整数(负整数 + 0) 
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 匹配正浮点数 
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 匹配负浮点数 
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ 匹配浮点数 
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 匹配非负浮点数(正浮点数 + 0) 
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 匹配非正浮点数(负浮点数 + 0)

常用字符串正则 正则 含义 补充 
^[A-Za-z]+$ 匹配由26个英文字母组成的字符串 或 /^[a-z]+$/i 
^[A-Z]+$ 匹配由26个英文字母的大写组成的字符串 
^[a-z]+$ 匹配由26个英文字母的小写组成的字符串 
^[A-Za-z0-9]+$ 匹配由数字和26个英文字母组成的字符串 注意\w包含下划线_ 
^\w+$ 匹配由数字、26个英文字母或者下划线组成的字符串 
常用数字正则和常用字符串正则,是最基本的正则应用,读者可以作为入门的练习,试试能不能快速的读懂其中的含义。

匹配中文字符 普遍使用的正则是[\u4e00-\u9fa5],但这个范围并不完整。例如: 
/[\u4e00-\u9fa5]/.test( '⻏' ) // 测试部首⻏,返回false 
根据Unicode 5.0版编码,要准确的判断一个中文字符要包括: 
范围 含义 范围 含义 
2E80-2EFF CJK 部首补充 2F00-2FDF 康熙字典部首 
3000-303F CJK 符号和标点 31C0-31EF CJK 笔画 
3200-32FF 封闭式 CJK 文字和月份 3300-33FF CJK 兼容 
3400-4DBF CJK 统一表意符号扩展 A 4DC0-4DFF 易经六十四卦符号 
4E00-9FBF CJK 统一表意符号 F900-FAFF CJK 兼容象形文字 
FE30-FE4F CJK 兼容形式 FF00-FFEF 全角ASCII、全角标点 
因此,正确的匹配中文字符正则表达式为: 
var rcjk = /[\u2E80-\u2EFF\u2F00-\u2FDF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FBF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF]+/g; 
如果不希望匹配标点、符号,在正则中去掉对应的范围即可: 
3000-303F CJK 符号和标点 FF00-FFEF 全角ASCII、全角标点

匹配双字节字符(包括汉字在内) [^\x00-\xff],可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1),代码示例如下: 
console.info( "abc".replace( /[^\x00-\xff]/g,"aa" ).length ) // 3 
console.info( "汉字".replace( /[^\x00-\xff]/g,"aa" ).length ) // 4 
console.info( "abc汉字".replace( /[^\x00-\xff]/g,"aa").length ) // 7

匹配HTML标记的正则表达式 先说说网上流传的版本: 
<(\S*?)[^>]*>.*?</\1>|<.*? /> 
*? *表示0个或多个,?表示0个或1个,两个叠加起来标识0个多个,与*的功能重叠 
(\S*?) 标签的长度必须大于0,因此不能用*? 
|<.*?\/> 没有分组,无法获取以<div/>这种自关闭格式书写的标签 
</\1> 
<.*? /> 有的标签是不关闭的,比如<br><hr>,因此不能强制关闭 
修正如下: 
var rtag = /^<([a-z]+)\s*\/?>.*(?:<\/\1>)?$/i 
rtag.exec( '<-div></-div>') // null 
rtag.exec( '<div>abc') // ["<div>abc", "div"] 
这个表达式也不完善,比如第二条测试语句,这么写是为了能提取中包含了文本内容的标签,如果要严格匹配,可再次修改为: 
var rtag = /^<([a-z]+)\s*\/?> (?:<\/\1>)?$/i // 去掉了中间的.* 
这个正则的应用范围仅限于简单的标签匹配、提取,不能匹配嵌套标记。

匹配首尾空白字符的正则表达式 先说说网上流传的版本: 
^\s*|\s*$ 
可以删除行首行尾的空白字符,例如: 
' \t \n\r abc \t \n\r '.replace( /^\s*|\s*$/g, '' ) // abc 
但是用\s*不能判断出字符串是否在开头或结尾处有\s,例如: 
/^\s*|\s*$/.test( 'abc' ) // true 
修正如下: 
^\s+|\s+$ 
' \t \n\r abc \t \n\r '.replace( /^\s+|\s+$/g, '' ) // abc 
/^\s+|\s+$/.test( 'abc' ) // false

匹配Email地址的正则表达式 先介绍下Email的规则:local-part@domain 
 local-part最长64,domain最长253,总长最长256 
 local-part可以使用任意ASCII字符: 
 大小写英文字母 a-z,A-Z 
 数字 0-9 
 字符 !#$%&'*+-/=?^_`{|}~ 
 字符 .不能是第一个和最后一个,不能连续出现两次 
 但是有些邮件服务器会拒绝包含有特殊字符的邮件地址 
 domain(域名)仅限于26个英文字母、10个数字、连词号- 
 连词号-不能是第一个字符 
 顶级域名(com、cn等)长度为2到6个 
先说说网上流传的版本: 
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 
() 莫名奇妙的分组,如果只分组不记录,可以使用(?:) 
@\w domain不能包含下划线_ 
\w+([-.]\w+)* 顶级域名不符合规则 
修正如下: 
var remail = /^([\w-_]+(?:\.[\w-_]+)*)@((?:[a-z0-9]+(?:-[a-zA-Z0-9]+)*)+\.[a-z]{2,6})$/i 
remail.exec( 'nuysoft@gmail.com' ) // "nuysoft@gmail.com", "nuysoft", "gmail.com"] 
remail.exec( 'nuysoft@gmail.comcomcom' ) // null 
remail.exec( 'nuysoft@_gmail.com ) // null 
修正后的正则有如下局限性: 
 不支持中文邮箱、中文域名,之所以不在其中支持是因为我个人的爱好倾向,反感这类华而不实的玩意 
 不支持特殊符号,避免非邮件服务器拒绝,如果需要,可以添加。 
参考文章: 
http://en.wikipedia.org/wiki/Email_address 
http://baike.baidu.com/view/119298.htm

匹配网址URL的正则表达式 先说说网上流传的版本: 
[a-zA-z]+://[^\s]* 
粗糙,没有对URL中各个块进行分组 
修正如下(又一段网上流传的版本): 
var _url = "^((https|http|ftp|rtsp|mms)?://)?" // 
+ "(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" // ftp的user@ 
+ "(([0-9]{1,3}.){3}[0-9]{1,3}" // IP形式的URL- 199.194.52.184 
+ "|" // 允许IP和DOMAIN(域名) 
+ "([0-9a-z_!~*'()-]+.)*" // 域名- www. 
+ "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]." // 二级域名 
+ "[a-z]{2,6})" // first level domain- .com or .museum 
+ "(:[0-9]{1,4})?" // 端口- :80 
+ "((/?)|" // a slash isn't required if there is no file name 
+ "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$"; 
var rurl = new RegExp( _url, 'i' ); 
测试: 
rurl.exec( 'baidu.com' ) // ["baidu.com", undefined, undefined, undefined, undefined, "baidu.com", undefined, "baid", undefined, undefined, "", "", undefined] 
rurl.exec( 'http://baidu.com' ) // 
rurl.exec( 'http://www.baidu.com' ) // ["http://baidu.com", "http://", "http", undefined, undefined, "baidu.com", undefined, "baid", undefined, undefined, "", "", undefined] 
rurl.test( 'baidu' ) // true 
看来不怎么也好用,有待学习TODO。

匹配帐号是否合法 先说说网上流传的版本: 
^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 
(字母开头,允许5-16字节,允许字母数字下划线) 
限制必须以字母开头现在看来不合适,比如QQ登录平台 
限制不能以下划线开头也没有必要,比如百度就允许,因此简单点 
修正如下: 
var ruser = /\w{4,16}/

匹配国内电话号码 网上流传的版本很好用: 
\d{3}-\d{8}|\d{4}-\d{7} 
评注:匹配形式如 0511-4405222 或 021-87888822

匹配腾讯QQ号 网上流传的版本很好用: 
[1-9][0-9]{4,} 
评注:腾讯QQ号从10000开始

匹配中国邮政编码 网上流传的版本很好用: 
[1-9]\d{5}(?!\d) 
评注:中国邮政编码为6位数字

匹配身份证 先说说网上流传的版本: 
\d{15}|\d{18} 
d{15} 
\d{18} 可以判断,但是有些粗糙 
从身份证可以解析出地址、生日、性别等,因此特别说明一下: 
 身份证规则 
中国的身份证为15位(一代)或18位(二代),区别在于二代证只是在一代证的第七位数字前加了19和在末尾加了一位验证码 
 将15位升级为18位,并解析18位号码构成(地址、生日、性别) 
代码如下: 
function parseID(ID) { 
if ( ID.length == 15 ) { 
// 升级为18位 
ID = ID.substr( 0, 6 ) + "19" + ID.substr( 6 ); 
// 前17位对应的系数 
var rank = [ 
"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2" 
]; 
// 前17为加权除以17后的余数对应的最后一位身份证号码 
var last = [ 
"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" 
]; 
// 加权和 
for ( var i = 0, sum = 0, len = ID.length; i < len; i++) 
sum += ID[ i ] * rank[ i ]; 
// 加上最后一位 
ID += last[ sum % 11 ]; 
} 
if ( ID.length != 18 ) return null; 
var match = rid.exec( ID ); 
return match ? { 
ID : ID, 
area : match[ 1 ], 
y : match[ 2 ], 
m : match[ 3 ], 
d : match[ 4 ], 
sex : match[ 5 ] % 2 
} : null; 
} 
限制: 
 这里只是解析出了地址代码,如何将代码转换为实际地址请问度娘。 
 返回对象中的sex为1(男)或0(女),并未做转换,如果页面显示需要,可以这样转换:sex ? "男" : "女" 
测试: 
console.info( parseID( "142327840821047" ) ); 
console.info( parseID("142327198408210470" ) ); 
参考资料: 
http://baike.baidu.com/view/118340.htm#1

匹配IP地址 先说说网上流传的版本: 
\d+\.\d+\.\d+\.\d+ 
\d 数字没有限制 
修正如下: 
var rip = /^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$/; 
rip.test( "192.168.1.1" ) // true 
rip.test( "0.0.0.0" ) // true 
rip.test( "255.255.255.255" ) // true 
rip.test( "256.255.255.255" ) // false 
进一步增加分组: 
var rip2 = /^([01]?\d{1,2}|2[0-4]\d|25[0-5])\.([01]?\d{1,2}|2[0-4]\d|25[0-5])\.([01]?\d{1,2}|2[0-4]\d|25[0-5])\.([01]?\d{1,2}|2[0-4]\d|25[0-5])$/; 
rip2.exec( "192.168.1.1" ) // ["192.168.1.1", "192", "168", "1", "1"] 
rip2.exec( "0.0.0.0" ) // ["0.0.0.0", "0", "0", "0", "0"] 
rip2.exec( "255.255.255.255" ) // ["255.255.255.255", "255", "255", "255", "255"] 
rip2.exec( "256.255.255.255" ) // null
Javascript 相关文章推荐
jquery select操作的日期联动实现代码
Dec 06 Javascript
JAVASCRIPT style 中visibility和display之间的区别
Jan 22 Javascript
限制textbox或textarea输入字符长度的JS代码
Oct 16 Javascript
让jQuery与其他JavaScript库并存避免冲突的方法
Dec 23 Javascript
详解JavaScript基本类型和引用类型
Dec 09 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
Feb 17 Javascript
巧用Javascript的逻辑运算符
Dec 02 Javascript
Node.js 实现简单的接口服务器的实例代码
May 23 Javascript
MvcPager分页控件 适用于Bootstrap
Jun 03 Javascript
react-native DatePicker日期选择组件的实现代码
Sep 12 Javascript
vue better-scroll插件使用详解
Jan 25 Javascript
JS三级联动代码格式实例详解
Dec 30 Javascript
jQuery源码分析-01总体架构分析
Nov 14 #Javascript
js Form.elements[i]的使用实例
Nov 13 #Javascript
jquery中使用ajax获取远程页面信息
Nov 13 #Javascript
JQuery模板插件 jquery.tmpl 动态ajax扩展
Nov 10 #Javascript
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
Nov 10 #Javascript
Javascript中的isNaN函数使用说明
Nov 10 #Javascript
推荐40个非常优秀的jQuery插件和教程【系列三】
Nov 09 #Javascript
You might like
如何给phpcms v9增加类似于phpcms 2008中的关键词表
2013/07/01 PHP
PHP中array_map与array_column之间的关系分析
2014/08/19 PHP
phpStudy访问速度慢和启动失败的解决办法
2015/11/19 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
2019/04/02 PHP
IE浏览器兼容Firefox的JS脚本的代码
2008/10/23 Javascript
js获取本机的外网/广域网ip地址完整源码
2013/08/12 Javascript
JQuery的常用选择器、过滤器、方法全面介绍
2016/05/25 Javascript
浅谈Vue的基本应用
2016/12/27 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
详解angularjs利用ui-route异步加载组件
2017/05/21 Javascript
seajs模块压缩问题与解决方法实例分析
2017/10/10 Javascript
vue 监听屏幕高度的实例
2018/09/05 Javascript
webpack4.x CommonJS模块化浅析
2018/11/09 Javascript
在Python中使用sort()方法进行排序的简单教程
2015/05/21 Python
Django REST为文件属性输出完整URL的方法
2017/12/18 Python
python使用itchat库实现微信机器人(好友聊天、群聊天)
2018/01/04 Python
python中int与str互转方法
2018/07/02 Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
2018/07/12 Python
如何利用python制作时间戳转换工具详解
2018/09/12 Python
python图像和办公文档处理总结
2019/05/28 Python
python OpenCV GrabCut使用实例解析
2019/11/11 Python
用python的turtle模块实现给女票画个小心心
2019/11/23 Python
使用tqdm显示Python代码执行进度功能
2019/12/08 Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
2019/12/12 Python
python用TensorFlow做图像识别的实现
2020/04/21 Python
Python新手学习标准库模块命名
2020/05/29 Python
经济管理专业毕业生自荐信范文
2014/01/02 职场文书
中专毕业生自我鉴定
2014/02/02 职场文书
小学生寒假家长评语
2014/04/16 职场文书
技校毕业生自荐信
2014/06/03 职场文书
建议书格式
2015/02/04 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
2015年度考核个人工作总结
2015/10/24 职场文书
2016年大学光棍节活动总结
2016/04/05 职场文书
python删除csv文件的行列
2021/04/06 Python
Nginx HTTP跳转至HTTPS
2022/05/15 Servers