一小时看懂正则表达式
正则表达式是程序员的一大装逼利器,看到一大推不人不鬼的符号,不会的人看了,心生恐惧,完全看不懂,对会用正则的人膜拜之极,我想将很多狠复杂的东西简单的传达出来,让不会的人不要对自己不懂的东西心生畏惧,学海无涯,吾生有涯,将自己感兴趣的某一块领域,再缩小,将自己感兴趣的某一点,做的好一点,再好一点,长期坚持,直至极致,不算白活
一、看几个非常常用的例子,不理解就背下来好了,背着背着就理解了
1、是否都为数字:^[0-9]*$ 2、是否为身份证号:/^(\d{15}$| \d{18} | \d{17}[xX])$/
3、手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
网上很多这样写,个人觉得有点戳
二、常用的元字符
\ : 转意,即通常在'\'后面的字符不按原来意义解释
. : 除了换行和回车之外的任意字符 ^ : 字符串开头,匹配一个输入或一行的开头 $ : 字符串结尾,匹配一个输入或一行的结尾 \b : 匹配单词的分界处(boundary) = [\t\n\r](单词边界就是单词和符号之间的边界) \B : not boundary \d : 数字(digit), 匹配一个数字,等价于[0-9] \D : not digits \s : 匹配一个单个white空格符,包括空格,tab,换行符,等价于[\f\n\r\t\v] \S : not space \w : 匹配字母,数字,下划线(word) \W : not word
eg:
\
/a*/.test('a,aa,aaa')' //true
/a\*/.test('a,aa,aaa') //false
/a\*/.test('a*')//true
alert('a,aa,aaa'.match(/a*/)) //a
alert('a,aa,aaa'.match(/a\*)) //null
alert('a*'.match(/a\*/)) //a*
.
/./.test('美')
//true
/./.test(' ')
//true
/./.test('')
//false
^
/^a/.test('an A')
//true
/^a/.test('bn A')
//false$
$
/a$/.test('an a')
//true
/a$/.test('an b')
//false
\s
/\s/.test('foobar')
//false
/\s/.test('foo bar')
//true
\r:匹配一个回车符
\n:匹配一个换行符
\f:匹配一个表单符
\t:匹配一个制表符
\v:匹配一个顶头制表符
\b
/\bn\w/.test('noonday')
//true
/\bn\w/.test('oonday')
//false
关于\b\b和^$
/\bword\b/.test('word')
//true
/^word$/.test('word')
//true
/\bword\b/.test('word d')
//true
/^word$/.test('word d')
//false
[\b]匹配一个空格
\d
/\d/.test('b2 is the suit number')
//true
/\d/.test('b is the suit number')
//false
\w
/\w/.test('$5.28')
//true
/\w/.test('$')
//false
三、正则表达式的复制字符
* : 匹配*前面的字符0次或n次,等价于{0,} + : 匹配+号前面的字符1次或多次,等价于{1,} ? : 匹配?前面的字符0次或1次,等价于{0,1} {n} : 这里的n是一个正整数。匹配前面的n个字符 {n,} : 这里的n是一个正整数,匹配至少n个前面的字符 {n,m} : 这里的n和m都是正整数,匹配至少n个最多m个前面的字符
eg:
*
/bo*/.test('b')
//true
/bo*/.test('o')
//false
/bo*/.test('a ghost boooooed')
//true
/bo*/.test('a bird wardlbd')
//true
/bo*/.test('a goat grunted')
//false
理解:*匹配数据中含有第一个字符或者存在连着的字符都返回true, bo*/匹配"A ghost booooed"中的'boooo'或"A bird warbled"中的'b',但不匹配"A goat grunted"中的任何字符
+:要大于|等于 1次
alert('candy'.match(/a+/)) //a
alert('caaaaaaaandy'.match(/a+/)) //aaaaaaaa
理解,只要数据中含有+前面的字符就返回true,/a+/匹配"candy"中的'a'和"caaaaaaandy."中的所有'a'
?
alert('aaaaa'.match(/a?/)) //a
{n}
/a{2}/.test('candy');
//false
/a{2}/.test('caandy');
//true
/a{2}/不匹配"candy,"中的'a',但匹配"caandy," 中的所有'a'和"caaandy."中前面的两个
{n,}
alert('candy'.match(/a{2,}/))
//null
alert('caandy'.match(/a{2,}/))
//aa
alert('caaandy'.match(/a{2,}/))
//aaa
/a{2,}不匹配"candy"中的'a',但匹配"caandy"中的所有'a'和"caaaaaaandy."中的所有'a'
{n,m}
/a{1,3}/.test('cndy')
//false
/a{1,3}/.test('candy')
//true
/a{1,3}/.test('caaandy')
//true
/a{1,3}/.test('caaaaaaaaaaady');
//true
/a{1,3}/不匹配"cndy"中的任何字符,但匹配 "candy,"中的'a',"caandy," 中的前面两个
'a'和"caaaaaaandy"中前面的三个'a',注意:即使"caaaaaaandy" 中有很多个'a',但只匹配前面的三个'a'即"aaa"。
四、选择,分组
[abc] : 或a或b或c [^abc] : 非a非b非c [a-c] : a-c的任意字符,这里跟1是一样的意思 [0-9] : === \d
eg:
[xyz]
[abcd]跟[a-d]一样 /[abcd]/.test('brisket') //true /[a-d]/.test('brisket') //true /[a-d]/.test('risket') //false 字符列表,匹配列出中的任一字符
[^abc]
[^abc] = [^a-c]
/^abc/.test('abcd')
//true
[^abc].test('abc')
//false
五、先行断言
(?=abc) 匹配abc前面的位置 官方说法,正向先行断言或者正向前瞻 (?!abc) 匹配后面不是abc的位置 官方说法,反向先行断言或则会负向前瞻,反正听这个肯定听不懂
这两个不用管,写在这里好看的,反正js都不支持
(?<=exp) 匹配exp后面的位置 官方说法 正向后瞻
(?<!exp) 匹配前面不是exp的位置 官方说法 负向后瞻
eg:
(?=abc) alert('regular'.match(/re(?=gular)/)) //re alert('regular'.match(/re(?=source)/)) //null (?!abc) alert('regular'.match(/re(?=gular)/)) //null alert('regular'.match(/re(?=source)/)) //re
六、正则表达式的一些属性
属性 注意RegExp对象的几个属性既有长名字又有短名字(象Perl)。这些名字都是指向相同的值。Perl是 一种编程语言,而JavaScript模仿了它的正则表达式。 属性$1, ..., $9 取得匹配的子串,如果有的话 属性$_ 参考input 属性$* 参考multiline 属性$& 参考lastMatch 属性$+ 参考lastParen 属性$` 参考leftContext 属性$' 参考rightContext 属性constructor 指定用来建立对象原型函 属性global 决定是否测试正则表达式是否不能匹配所有的字符串,或者只是与最先的冲突。 属性ignoreCase 决定试图匹配字符串的时候是否忽略大小写 属性input 当正则表达式被匹配的时候,为相反的字符串。 属性lastIndex 决定下一次匹配从那里开始 属性lastMatch 最后一个匹配的字符 属性lastParen 子串匹配的时候,最后一个parenthesized,如果有的话。 属性leftContext 最近一次匹配前的子串。 属性multiline 是否在串的多行中搜索。 属性prototype 允许附加属性到所有的对象 属性rightContext 最近一次匹配后的的子串。 属性source 模式文本
七、正则表达式的一些方法
compile方法
编译一个正则表达式对象
exec方法
运行正则表达式匹配
test方法
测试正则达式匹配
toSource方法
返回一个对象的文字描述指定的对象;你可以使用这个值来建立一个新的对象。不考虑Object.toSource方法。
toString方法
返回一个字符串描述指定的对象,不考虑Object.toString对象。
valueOf方法
返回指定对角的原始值。不考虑Object.valueOf方法。
另外,这个对象继承了对象的watch和unwatch方法
十、常用正则表达式集锦
1、校验数字的表达式
数字:^[0-9]*$ n 位的数字:^\d{n}$ 至少 n 位的数字:^\d{n,}$ m-n 位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9][0-9]*)$ 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$ 正数、负数、和小数:^(-|+)?\d+(.\d+)?$ 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$ 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$ 非零的正整数:^[1-9]\d$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]*$ 非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$ 非负整数:^\d+$ 或 ^[1-9]\d*|0$ 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ 非负浮点数:^\d+(.\d+)?$ 或^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$ 非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$ 正浮点数:^[1-9]\d.\d|0.\d[1-9]\d$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$ 负浮点数:^-([1-9]\d.\d|0.\d[1-9]\d)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$ 浮点数:^(-?\d+)(.\d+)?$ 或^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$
2、校验字符的表达式
汉字:^[\u4e00-\u9fa5]{0,}$ 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ 长度为3-20的所有字符:^.{3,20}$ 由26个英文字母组成的字符串:^[A-Za-z]+$ 由26个大写英文字母组成的字符串:^[A-Z]+$ 由26个小写英文字母组成的字符串:^[a-z]+$ 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{1,20}$ 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$ 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ 可以输入含有^%&’,;=?$\”等字符:[^%&',;=?$\x22]+ 禁止输入含有~的字符:[^~\x22]+ 不以xxx(如 jeffjade )开头(/结尾)的字符串:^(?!jeffjade).*$
3、特殊需求的表达式
Email地址:^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$ 或 \w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14} 域名地址:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ 身份证号(15位、18位数字):^\d{15}|\d{18}$ 是否合法Url地址 // 必须包含http or https https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*) // 不必包含http or https [-a-zA-Z0-9@:%._\\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*) 是否合法帐号: // 允许3到16个字节,仅包含字母或数字 ^[a-zA-Z0-9]{3,16}$ // 字母开头,允许5-16字节,允许字母数字下划线 ^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 是否合法密码 // 至少八个字符,至少一个字母和一个数字: ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$ // 至少八个字符,至少一个字母,一个数字和一个特殊字符: ^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$ // 最少八个字符,至少一个大写字母,一个小写字母和一个数字 "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$" // 至少八个字符,至少一个大写字母,一个小写字母,一个数字和一个特殊字符: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}" // 最少八个最多十个字符,至少一个大写字母,一个小写字母,一个数字和一个特殊字符: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,10}"