正则表达式知识详解
一、什么是正则表达式?
1.定义:
正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
2.组成:
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
3.何时使用:验证——从头到尾完整匹配!
查找——只要部分匹配即可!
二、正则表达式的基本语法和规则
1.备选字符集:规定某*一位字符*可用的备选字符的集合
语法:[可选字符列表]
强调:1. 无论备选字符集包含多少字符,只能选1个
2. 必须选1个!
比如:6位数字的密码
[0123456789][0123456789][0123456789][0123456789][0123456789][0123456789]
简化:1. 当备选字符连续时,可用-表示范围的区间
比如:[0123456789]-->[0-9]
[0-9][0-9][0-9][0-9][0-9][0-9]
[a-z]-->1位小写字母
[A-Z]-->1位大写字母
[A-Za-z]-->1位字母,大小写都行
[0-9a-zA-Z]-->1位字母或数字都行
反选:[^不能选的字符列表]
比如:[^47] 强调:^作“除了”使用时,只能放在开头
2. 预定义字符集:为常用的字符集专门提供的简化写法!
“\d”-->[0-9]-->1位数字
“\w”-->[0-9a-zA-Z_]-->1位字母,数字或_
“\s”-->1位空字符:匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
“ . “: 除换行回车外的任何一个字符,如:
"a.[0-9]":表示一个字符串有一个"a"后面跟着一个任意字符和一个数字;
"^.{3}$":表示有任意三个字符的字符串(长度为3个字符)
\t--------匹配一个制表符
预定义字符的反义:预定义字符的大写形式都是小写的反义
\D---->1位非数字字符
\S------匹配任何非空白字符。等价于 [^\f\n\r\t\v]。
\v------匹配一个垂直制表符
\n------匹配一个换行符
\r-------匹配一个回车符
3. 数量词:规定相邻的字符集可出现的次数
确定数量:3种:
{n}--> 必须反复出现n位
{n,m}--> 最少出现n次,最多出现m次
{n,}-->至少出现n次,多了不限!
比如:/^\d{6}$/——6位数字
手机号规则:
第1位:只能是1
第2位:[34578]
第3位之后,必须是9位数字
手机号:/^1[34578]\d{9}$/
不确定数量:3种:
*: 有没有都行,次数不限,相当于{0,}
+: 至少1次,重复次数不限,相当于{1,}
?: 有没有都行,最多1次,相当于{0,1}
():分组
|: 左右两正则表达式选其一
身份证号逻辑:
前15位数字
16,17位必须是数字
最后一位可以是数字或X x
后三位 可有可无,如果有,只能出现一次
\d{15}(\d\d[0-9Xx])?
手机号:
手机号前可能出现+86或0086。
前缀可有可无,且只能出现一次
前缀和手机号之间可以有或没有任意个空字符
第1位:只能是1
第2位:[34578]
第3位之后,必须是9位数字
手机号:
(\+86|0086)?\s*1[34578]\d{9}
4. 指定匹配位置:
^表达式: 必须以表达式的规则为开头
表达式$: 必须以表达式的规则为结尾
比如:选择字符串开头的空格?^\s*
选择结尾空格?\s*$
选择开头或结尾的空格?^\s*|\s*$
*预告:今后只要在程序中执行验证:都要前加^后加$*
表示从头到尾完整匹配。
比如:test():
^\d{6}$——从头到尾必须只能是6位数字
1234567
5. 预判:在正式匹配正则表达式之前,先预读整个字符串,进行初步匹配,如果预判都未通过,则不再验证!
1)(?=表达式): 先浏览字符串是否满足表达式的要求
何时使用:只要正则中出现类似"而且"
比如:4位数字,但不能包含4和7
(?=[^47]$) 是否由除了4,7之外的字符组成
2)(?!表达式):先检查字符串是否不满足表达式要求
比如:6位以上密码。
字母,数字组成
首字母不能是数字: [a-zA-Z][a-zA-Z0-9]{5,}
必须至少包含1个大写字母
不能都由小写字母和数字组成: (?![a-z0-9]+$)
必须至少包含1个数字
不能都由小写字母和大写字母组成:
(?![a-zA-Z]+$)
6.特殊字符
所谓特殊字符,就是一些有特殊含义的字符,如"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个\。ls \*.txt。许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符 (\) 放在它们前面。下面列出了正则表达式中的特殊字符:(请注意在方括号中,不需要转义字符。)
“$”------匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
“()”----标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
“*”----匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
“+”-----匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
“.”----匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \.。
“[”------标记一个中括号表达式的开始。要匹配 [,请使用 \[。
“?”----匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
“\”----将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "(".
“^”-----匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
“{”----标记限定符表达式的开始。要匹配 {,请使用 \{。
“|”----指明两项之间的一个选择。要匹配 |,请使用 \|。
7. 贪婪模式和懒惰模式:
贪婪模式:默认情况下,正则表达式会匹配最大的符合条件的字符串, *、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
贪婪模式原因:(.*) (.+)
懒惰模式:正则表达式仅匹配最小的符合规则的字符串
比如:筛选网页中的a元素:
<a\s+(.*)href\s*=\s*["']([^'"]*)["']
贪婪模式-->懒惰模式:.*?
例如:
您可能搜索 HTML 文档,以查找括在 H1 标记内的章节标题。该文本在您的文档中如下:
<h1> Chapter 1 - Introduction to Regular Expression</h1>
下面的表达式匹配从开始小于符号 (<) 到关闭 H1 标记的大于符号 (>) 之间的所有内容。
/<.*>/
如果您只需要匹配开始 H1 标记,下面的"非贪心"表达式只匹配 <H1>。
/<.*?>/
通过在 *、+ 或 ? 限定符之后放置 ?,该表达式从"贪心"表达式转换为"非贪心"表达式或者最小匹配。
三、常用正则表达式示例及说明:
1.正则表达式验证控制文本框的输入字符类型
1)只能输入数字和英文的:
<input οnkeyup="value=value.replace(/[\W]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" ID="Text1" NAME="Text1">
2)只能输入数字的:
<input οnkeyup="value=value.replace(/[^\d]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" ID="Text2" NAME="Text2">
3)只能输入全角的:
<input οnkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))" ID="Text3" NAME="Text3">
4)只能输入汉字的:
<input οnkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))" ID="Text4" NAME="Text4">
2.正则表达式的应用实例通俗说明
*******************************************************************************
//校验是否全由数字组成
/^[0-9]{1,20}$/
^ 表示打头的字符要匹配紧跟^后面的规则
$ 表示打头的字符要匹配紧靠$前面的规则
[ ] 中的内容是可选字符集
[0-9] 表示要求字符范围在0-9之间
{1,20}表示数字字符串长度合法为1到20,即为[0-9]中的字符出现次数的范围是1到20次。
/^ 和 $/成对使用应该是表示要求整个字符串完全匹配定义的规则,而不是只匹配字符串中的一个子串。
*******************************************************************************
//校验登录名:只能输入5-20个以字母开头、可带数字、“_”、“.”的字串
/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/
^[a-zA-Z]{1} 表示第一个字符要求是字母。
([a-zA-Z0-9]|[._]){4,19} 表示从第二位开始(因为它紧跟在上个表达式后面)的一个长度为4到9位的字符串,它要求是由大小写字母、数字或者特殊字符集[._]组成。
*******************************************************************************
//校验用户姓名:只能输入1-30个以字母开头的字串
/^[a-zA-Z]{1,30}$/
*******************************************************************************
//校验密码:只能输入6-20个字母、数字、下划线
/^(\w){6,20}$/
\w:用于匹配字母,数字或下划线字符
*******************************************************************************
//校验普通电话、传真号码:可以“+”或数字开头,可含有“-” 和 “ ”
/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/
\d:用于匹配从0到9的数字;
“?”元字符规定其前导对象必须在目标对象中连续出现零次或一次
可以匹配的字符串如:+123 -999 999 ; +123-999 999 ;123 999 999 ;+123 999999等
*******************************************************************************
//校验URL
/^http[s]{0,1}:\/\/.+$/ 或 /^http[s]{0,1}:\/\/.{1,n}$/ (表示url串的长度为length(“https://”) + n )
\ / :表示字符“/”。
. 表示所有字符的集
+ 等同于{1,},就是1到正无穷吧。
*************************************************************************
三、RegExp 对象和方法
在Javascript中,通过RegExp对象来支持正则表达式。创建正则表达式的方式有两种:
1.最简单的创建正则表达式的方法:字面量形式
Var expression=/pattern/flags
其中pattern部分可以使任何简单的正则表达式
Flags表示正则表达式的标志,正则表达式的匹配模式支持3个标志:
1)”g”:表示全局(globle)模式,即模式被应用于所有字符串,而非在发现第一个匹配项是立即停止。
2)“i”:表示不区分大小写模式,即在确定匹配项是忽略模式于字符串的大小写。
3)“m”:表示多行模式,即在到达一行文本末尾是还会继续查找下一行中是否存在与模式匹配的项。例如:
/*匹配字符串中所有”at”的实例*/
Var paatern1=/at/g;
/*匹配第一个”bat”或”cat”,不区分大小写*/
Var paatern2=/[bc]at/i;
/*匹配所有以”at”结尾的3个字符串的组合,不区分大小写*/
Var paatern2=/.at/gi;
2.使用RegExp构造函数创建正则表达式
Var expression=new Regexp(“[bc]at”,”i”);
其中传给RegExp构造函数的两个参数都是字符串(不能把正则表达式的字面量传递给RegExp构造函数),也因此,在某些情况下要对字符进行双重转义。所有的元字符都必须进行双重转义。例如:
字面量模式:
/\[bc\]at/ /\.at/ /name\/age/ /\d.\d{1,2}/ /\w\\hello\\123/
等价的字符串形式:
“\\[bc\\]at” “\\.at” “name\\/age” “\\d.\\d{1,2}” “\\w\\\\hello\\\\123”
注意:使用正则表达式字面量和使用RegExp构造函数创建的正则表达式不一样,正则表达式字面量始终会共享同一个RegExp实例,而构造函数创建的每一个新RegExp实例都是一个新实例(动态创建的)。
3.Exec() 查找方法
Exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项的信息的数组,如果没有找到则返回null。返回的数组包含两个属性:index和input,index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串。
对于exec()而言即使在模式中设置了全局模式(g),它每次也只会返回一个匹配项,但是如果设置了全局模式,每次调用它都会返回字符串中的下一个匹配项,知道搜索到字符串的末尾为止。所以自全局匹配模式下,lastIndex的值在每次调用exec()后,都会增加,所以要想获取所有的匹配项内容和下标,需要循环获取。而在非全局模式下lastIndex则始终不变。
4.test()验证方法
此方法要求验证的字符串和正则表达式从头到尾完全匹配,需要”^”和”$”符号。
Reg.test(str): 如果匹配,返回true,否则返回false。Test()方法经常被用在if语句中,经常被用在验证用户输入的情况下,验证用户输入是不是有效。
例如:
Var text=”000-00-0000”;
Var pattern=/\d{3}-\d{2}-\d{4}/;
If(pattern.test(text)){
Atert(“the pattern was matched”);
}