正则表达式详解及应用
1.正则表达式简介 正则表达式(Regular expression,简写为Regexes)是一种用来操作和检验字符串数据的强大工具。它相当与一串特殊的字符,用它可以转换成算法,对文本进行匹配等操作。 事实上正则表达式有其自身的一套语法,这种语法对于初学者来说显得有些晦涩难懂。尤其是其构造比较困难,称为很多入门者的障碍。但当掌握后却可以轻易的解决以前不容易解决的很多文本类问题,如验证提取等。 其常用场合有如下三种: ? 测试字符串的某个模式。例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。 ? 替换文本。可以在文档中使用一个正则表达式来标识特定文字,然后可以全部将其删除,或者替换为别的文字。 ? 根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。 2.正则表达式基础语法 2.1匹配不同类型的字符
2.2定位控制字符
2.3指定重复字符
2.4特殊控制类
2.5 特殊字符转义序列
2.6正则表达式分组、替换、反向引用等高级应用 以上只是正则表达式的基础部分,从这里开始才算真正开始正则表达式之旅。 2 分组 分组技术可以匹配在一个组中的所有字符,用()来表示,是下面两个技术的基础所在。“()“又称捕获符号。 1. 捕获:() 例子:ABC1EDF2UU 匹配组表达式:([A-Z]{3})d --匹配3个连续大写字母和一个数字 匹配结果:1.ABC1,2.EDF2 如果用C#中的group,则为ABC,EDF。因为group搜集的是匹配组的内容。 使用了非捕获就说明该()中的内容将不作为捕获的组返回,而和其它表达式共同构成匹配项返回。也就是捕获组将不存在。 例:1AF3EDC 匹配表达式:(?:d|[A-Z])w --匹配一个数字或字母加一个任意的字符。 匹配结果:1.1A 2.F3 3.ED 没有组被捕获 2. 通过名称捕获(?<name>) 定义了名称捕获的组可以在反向匹配中运用名称进行反向引用而不需要再使用数字进行反向捕获。注意组名区分大小写! 2 替换 替换,顾名思义,是将匹配的字符替换成其他指定的字符形式。这个功能是在分组的基础上的(当然或许可以单独存在,但是那样匹配的功能显然不够强大)。在这里有一个技巧是使用附加的匹配字符控制匹配内容。
2 反向引用 反向匹配可以引用前面组中的匹配形式。“匹配组的数字表示(1为基数)“或者”k<groupname>“ 2 高级组 1. 正声明(?=) 规定了括号中的模式必须出现在声明的右侧。模式将不构成匹配的一部分。 2. 负声明(?!) 规定了括号中的模式不能出现在声明的右侧,模式将不构成匹配的一部分。 3. 反向正声明(?<=) 规定了括号中的模式必须出现在声明的左侧,模式将不构成匹配的一部分。 4. 反向负声明(?<!) 规定了括号中的模式必须出现在声明的左侧。模式不构成匹配的一部分。 5. 非回溯(?>) 防止了正则表达式引擎搜索失败时回溯,这称之为贪婪的子表达式。 如输入字符串:He was very trusting. 正则表达式:.*ing将匹配trusting但是如果加入(?>)ing则不能完成匹配。 非回溯组也是非捕获组。他对于提高正则表达式的效率很有效。 如匹配一个www.****.com的网址。使用www.(.*).com显然要比www.([^.]*).com效率要低的多,因为前者必须使用组中的回溯操作,回溯是很艰难的过程,所以当使用非回溯的正则表达式时时可以显著提高正则表达式的效率的。 其实正则表达式是只注重匹配结果的,所以会努力去匹配所存在的字符串。这就是它的贪婪性所在。(这点其实理解的不是太深)。 注意以上这些(1-5)都不能够用于反向引用,因为以上声明将不作为匹配的一部分。 2.7在正则表达式中做决策 高级决策的两种写法: 1=>(?(expression)yes|no) 2=>(?(?=expression)yes|no) 这两种方式中的的expression匹配则后面进行匹配yes,否则匹配no。 需要注意的一点是yes测试和决策测试是在同一个起点里进行的。 如以下字符串:77-77A 69-AA 57-B 匹配表达式为:(d7)?-(?(1)dd[A-Z]|[A-Z][A-Z]) 匹配结果为: 1.77-77A 2. –AA 这个正则表达式中用到了引用组,(?(1)**)中的1也可以换为1,这样不影响匹配。这个匹配中如果将决策后面的dd去掉则会出现不同的结果,这时只会有一个-AA是匹配的。因为决策点和yes表达式是从同一个起点开始匹配所以即使决策点匹配了,但是后面的yes表达式仍然不匹配。就只匹配no部分的表达式。最终结果也必然改变,理解这一点很重要。 2.8 正则表达式的选项 快到结尾了,再说下正则表达式的选项。选项其实就是将正则表达式的设置改到组中来。如(?i:[a-z])将忽略大小写进行匹配。实际上如果学过Javascript中的正则表达式,可以看出这个i在javascript中表示的还是这个意思。
2.9正则表达式的规则 1.正则表达式会对输入字符传进行最快的匹配,它一次搜索一个字符,知道实现第一次匹配。 2.发现一个匹配的开始后,正则表达式引擎将继续匹配,直到遇到一个不被模式接收的字符。 3.Regex引擎非常贪婪—只要模式匹配它将匹配尽可能多的字符。 4.Regex渴望实现匹配,所以将在需要时回溯以实现匹配。 5.Regex引擎总是先选择第一个选项。在|式表达式中。 以上的几点很重要。到这正则表达式的几乎所有规则也就讲完了。 最后附一个懒惰匹配常用修饰和其他的限定
应用: 匹配中文字符的正则表达式:
[
u4e00
-
u9fa5
]
匹配双字节字符(包括汉字在内):
[
^
x00
-
xff
]
应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String
.
prototype
.
len
=
function
(){
return
this
.
replace
([
^
x00
-
xff
]
/
g,"aa").length; }
匹配空行的正则表达式:
n
[
s
|
]
*
r
匹配HTML标记的正则表达式:
/
<(.*)>.*<
/
1>|<(.*)
/
>
/
匹配首尾空格的正则表达式:
(
^
s
*
)
|
(
s
*$
)
应用:j avascript中没有像v bscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
String
.
prototype
.
trim
=
function
()
{ return this . replace ( / (^s*)|(s*$) /g , "" ) ; } 利用正则表达式分解和转换IP地址
function
IP2V
(
ip
)
{ re = / (d+).(d+).(d+).(d+) /g //匹配IP地址的正则表达式 if ( re . test ( ip )) { return RegExp .$ 1 * Math . pow ( 255 , 3 ) )+ RegExp .$ 2 * Math . pow ( 255 , 2 ) )+ RegExp .$ 3 * 255 + RegExp .$ 4 * 1 } else { throw new Error ( " Not a valid IP address! " ) } } 不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var
ip
=
"
10.100.20.168
"
ip = ip . split ( " . " ) alert ( " IP值是: " + ( ip [ 0 ] * 255 * 255 * 255 + ip [ 1 ] * 255 * 255 + ip [ 2 ] * 255 + ip [ 3 ] * 1 )) 匹配Email地址的正则表达式:
w
+
([
-+.
]
w
+
)
*@
w
+
([
-.
]
w
+
)
*.
w
+
([
-.
]
w
+
)
*
匹配网址URL的正则表达式:
http
:
//([w-]+.)+[w-]+(/[w- ./?%&=]*)?
利用正则表达式去除字串中重复的字符的算法程序:[*注:此程序不正确]
var
s
=
"
abacabefgeeii
"
var s1 = s . replace ( / (.).*1 /g , " $1 " ) var re = new RegExp ( " [ " + s1 + " ] " , " g " ) var s2 = s . replace ( re , "" ) alert ( s1 + s2 ) //结果为:abcefgi *注 我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。 得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1
s
=
"
http://blog.penner.cn/page1.htm
"
s = s . replace ( / (.* / ){ 0,}([^.]+).* /i g , " $2 " ) alert ( s ) 利用正则表达式限制网页表单里的文本框输入内容: 用正则表达式限制只能输入中文:
onkeyup
=
"
value=value.replace(/[^u4E00-u9FA5]/g,'')
"
onbeforepaste
=
"
clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))
"
用正则表达式限制只能输入全角字符:
onkeyup
=
"
value=value.replace(/[^uFF00-uFFFF]/g,clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))
"
用正则表达式限制只能输入数字:
onkeyup
=
"
value=value.replace(/[^d]/g,'')
"
onbeforepaste
=
"
clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))
"
用正则表达式限制只能输入数字和英文:
onkeyup
=
"
value=value.replace(/[W]/g,''))
"
匹配非负整数(正整数 + 0)
^
d
+$
匹配正整数
^
[
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*$
匹配非正整数(负整数 + 0)
^
((
-
d
+
)
|
(
0
+
))
$
匹配负整数
^-
[
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*$
匹配整数
^-?
d
+$
匹配非负浮点数(正浮点数 + 0)
^
d
+
(
.
d
+
)
?$
匹配正浮点数
^
(([
0
-
9
]
+.
[
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*
)
|
([
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*.
[
0
-
9
]
+
)
|
([
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*
))
$
匹配非正浮点数(负浮点数 + 0)
^
((
-
d
+
(
.
d
+
)
?
)
|
(
0
+
(
.0
+
)
?
))
$
匹配负浮点数
^
(
-
(([
0
-
9
]
+.
[
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*
)
|
([
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*.
[
0
-
9
]
+
)
|
([
0
-
9
]
*
[
1
-
9
][
0
-
9
]
*
)))
$
匹配浮点数
^
(
-?
d
+
)(
.
d
+
)
?$
匹配由26个英文字母组成的字符串
^
[
A
-
Za
-
z
]
+$
匹配由26个英文字母的大写组成的字符串
^
[
A
-
Z
]
+$
匹配由26个英文字母的小写组成的字符串
^
[
a
-
z
]
+$
匹配由数字和26个英文字母组成的字符串
^
[
A
-
Za
-
z0
-
9
]
+$
匹配由数字、26个英文字母或者下划线组成的字符串
^
w
+$
匹配email地址
^
[
w
-
]
+
(
.
[
w
-
]
+
)
*@
[
w
-
]
+
(
.
[
w
-
]
+
)
+$
匹配url
^
[
a
-
zA
-
z
]
+:
//匹配(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
匹配html tag
<
s
*
(
S
+
)(
s
[
^>
]
*
)
?>
(
.*?
)
<
s
*
/
1s*>
Visual Basic & C# Regular Expression [Visual Basic]
Function IsValidEmail(strIn As String) As Boolean
' Return true if strIn is in valid e-mail format. Return Regex.IsMatch(strIn,("^([w-.]+)@(([[0-9]{ 1,3 }.[0-9]{ 1,3 }.)|(([w-]+.)+))([a-zA-Z]{ 2,4 }|[0-9]{ 1,3 })(]?)$") End Function [C#]
bool IsValidEmail(string strIn)
{ // Return true if strIn is in valid e-mail format. return Regex.IsMatch(strIn,@"^([w-.]+)@(([[0-9]{ 1,3 })(]?)$"); } 2.清理输入字符串 [Visual Basic]
Function CleanInput(strIn As String) As String
' Replace invalid characters with empty strings. Return Regex.Replace(strIn,"[^w.@-]","") End Function [C#]
String CleanInput(string strIn)
{ // Replace invalid characters with empty strings. return Regex.Replace(strIn,@"[^w.@-]",""); } 3.更改日期格式 [Visual Basic]
Function MDYToDMY(input As String) As String
Return Regex.Replace(input,_ "b(?<month>d{ 1,2 })/(?<day>d{ 1,2 })/(?<year>d{ 2,4 })b",_ "${ day }-${ month }-${ year }") End Function [C#]
String MDYToDMY(String input)
{ return Regex.Replace(input,"b(?<month>d{ 1,2 })/(?<day>d{ 1,2 })/(?<year>d{ 2,4 })b","${ day }-${ month }-${ year }"); } Regex 替换模式 有几种静态函数使您可以在使用正则表达式操作时无需创建显式正则表达式对象,而 Regex.Replace 函数正是其中之一。如果您不想保留编译的正则表达式,这将给您带来方便 4.提取 URL 信息 [Visual Basic]
Function Extension(url As String) As String
Dim r As New Regex("^(?<proto>w+)://[^/]+?(?<port>:d+)?/",_ RegexOptions.Compiled) Return r.Match(url).Result("${ proto }${ port }") End Function [C#]
String Extension(String url)
{ Regex r = new Regex(@"^(?<proto>w+)://[^/]+?(?<port>:d+)?/", RegexOptions.Compiled); return r.Match(url).Result("${ proto }${ port }"); } 只有字母和数字,不小于6位,且数字字母都包含的密码的正则表达式
"
w{ 6 }(w+)*
"
一个将需要将路径字符串拆分为根目录和子目录两部分的算法程序,考虑路径格式有:C:aabbcc ,aabbcc , ftp://aa.bb/cc 上述路径将分别被拆分为:C:和aabbcc ,aa 和 bbcc , ftp:// 和 aa.bb/cc 用javascript实现如下:
var
strRoot
,
strSub
var regPathParse = / ^([^^ / ]+[ / ]+|\[^]+)(.*)$ / if ( regPathParse . test ( strFolder )) { strRoot = RegExp .$ 1 strSub = RegExp .$ 2 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |