正则表达式
概念: 正则表达式是一种处理文本的工具,和其他工具一样,是人们为了解决某一类专门问题而发明的。正则表达式是正则表达式语言创建的,一些用来匹配和处理文本的字符串。
作用: 正则表达式的作用主要是用于文本匹配和替换。
匹配
一:匹配单个字符串
1、匹配纯文本。
纯文本正则表达式匹配原始文本内对应字符。
如下面文本输入Ben。
hello,my name is Ben.
匹配出来的结果就是:Ben
2、字母大小写问题。
在正则表达式的匹配结果是区分字母的大小写的,Ben只能匹配出Ben,而无法匹配出ben、BEN……等。
3、匹配任意字符。
在正则表达式里,字符 . 可以匹配任何一个单个字符,字母、数字设置是.字符本身。
4、匹配特殊字符。
.字符在正则表达式里有着特殊的含义。如果匹配模式里需要匹配出一个.,就需要在开头加进行转义,如果要匹配这需要\。
二:匹配一组字符
1、字符集合区间
匹配集合区间里面的任何一个字符元素。
如:要匹配文本中na1.xls、na2.xls、sa1.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
ca2.xls
正则表达式:[sn]a..xls
常用的字符集合区间
[0-9]等价[0123456789]:可以匹配数字0123456789中的任意一个。
[a-z]:可以匹配a到z的所有小写字母。
[A-Z]:可以匹配A到Z的所有大写字母。
[a-zA-Z]:匹配所有大小写字母。
[0-9a-zA-Z_]:匹配所有字符和数字和下划线。
2、取非匹配。
字符集合通常用来指定一组必须匹配其中之一的字符。但在某些场合,我们需要反过来做,给出一组不需要得到的字符。换句话说就是,除了那个字符集合的字符,其他的字符都可以匹配。
在集合前加元字符^来表明想对一个字符集合进行取非匹配。
如:[^sn]a..xls :表示开头字母不是s和n的,第二个字母是a的和后缀是.xls的所有字符串。
三:元字符。
元字符大致可以分为两种:一种是用来匹配文本的,比如是 . ,另外一种是正则表达式所要求的,比如[]。
1、对特殊字符进行转义。
元字符是一些在正则表式里有着特殊含义的字符。因为字符.是一个元字符,他可以用来匹配任何一个单个字符。[表示一个集合的开始,]表示一个集合的结束。
也因为元字符在正则表达式里有着特殊的含义,所以这些字符就无法表达他们本身。如不能使用.来表示.,不能使用[和]来表示[和]。要想表示他们,需要在他们前加上转义字符,如.表示.,[和]表示[和]。
如:myArray[[0-9]] :表示myArray[0]-myArray[9]。
2、常用一些元字符。
①、[]回退并删除一个字符
②、f换页符
③、 换行符
④、 回车符
⑤、 制表符
⑥、v垂直制表符
Windows使用
文本行结束标签。Unix和Linux只用一个
。
元字符d等价[0-9];元字符D等价[^0-9]
元字符w等价[a-zA-Z0-9];W等价[^a-zA-Z0-9]
元字符s等价[f
v];S等价[^f
v]
十六进制x ,八进制
3、POSIX字符类:
①[:alnum:]等价[a-zA-Z0-9]
[:alpha:]等价[a-zA-Z]
[:blank:]等价[ ]
④[:cntrl:]等价ASCII控制字符,即0-31,127
[:digit:]等价[0-9]
[:graph:]等价[:print:]-空格
[:lower:]等价[a-z]
[:print:]等价任一可打印字符
[:punct:]等价不是①④的
[:space:]等价[^f
v]
[:upper:]等价[A-Z]
[:xdigit:]等价[a-fA-F0-9
四:多个匹配
1、元字符+ ,用于字符和集合之后,匹配一个或多个字符(至少一个;不匹配零个字符的情况)。匹配+本身,用+
2、当在字符集合里,像.和+这样的元字符将被解释为普通字符,不需要转义。
3、*与+用法相同,*匹配字符或集合连续出现零次或多次的情况。
4、元字符? ,只能匹配一个字符(或集合)的零次或一次出现。
5、精确设置匹配次数,元字符{}作用:
①可设置重复匹配次数,如{5},则需要连续5次。
②可设置重复匹配区间{2,4},2-4次
③可设置至少匹配次数{3,},3次以上
6、* 和 + 都是“贪婪型”元字符,其匹配行为多多益善。此时,可使用?后缀将其转化为“懒惰型”版本。如“贪婪型”:* + {n,} ,“懒惰型”:*? +? {n,}?
如:文本This offer is not available to customers living in <B>AK</B> and <b>HI</B>.
贪婪式:正则表达式:<[Bb]>.*</[Bb]> 匹配的结果是:<B>AK</B> and <b>HI</B>
懒惰型:正则表达式:<[Bb]>.*?</[Bb]> 匹配的结果是:<B>AK</B> 和 <b>HI</B>.
五:位置匹配
1:边界
如果要在这个句子里:The cat scattered his food all over the room.
正则表达式:cat
上面的正则表达式会把所有的cat都找出来,单词scattered里的cat也不会例外。如果我们只是要把句子中的cat单词找出来。办法只有一个,就是使用边界限定符,也就是在正则表达式里用一些特殊的元字符来说明我们想匹配操作在什么位置发生。
(1)单词边界
第一种边界也是最常用的边界是由限定符指定的单词边界。是用来匹配一个单词的开始和结尾。
在上面的例子里,使用边界限定符输入:
正则表达式:cat
匹配出来的结果就是单词:cat
注意:正则表达式引擎不懂得英语,更不懂任何人类语言,也不知道什么是单词边界。简单地说:其实匹配的是这样的一个位置,这个位置位于一个能够用来构成单词的字符(包括字母,数字和下划线 即w)和一个不能用来构成单词的字符(也就是W相匹配的字符)之间。只匹配一个位置,不匹配任何的字符,用cat匹配到的字符串的长度是3个字符。
如果想表明不匹配一个单词边界,使用B。在下面例子里,使用B来查找一个前后都不是单词的边界的连字符-。
句子:Please enter the nine-digit id as it appears on your color - coded pass-key.
正则表达式:w+-w+
结果:nine-digit 和 pass-key.
正则表达式:B-B
结果:- (匹配前后都不是单词边界的连字符)
注意:如果相匹配一个完整的单词,就必须在你想要匹配的文本的前后都加上限定符。
例子:
句子:The captain wore his cap and cape proudly as he sat listening to the recap of his crew saved the men from a capsized vessel.
正则表达式:cap
解析:只是匹配以cap开头的单词。结果:captain cap cape capsized
正则表达式:cap
解析:只是匹配以cap结尾的单词。结果:cap recap
正则表达式:cap
解析:匹配cap单词本身。结果:cap
(2)字符串边界
单词边界可以用来进行与单词有关的位置匹配(单词的开头,单词的借宿、整个单词等等……)。字符串边界有类似的用途,只不过是用来进行字符串有关的位置匹配而已(字符串的开头、字符串的借宿、整个字符串等等……)。用来定义字符串边界的元素有两个:一个用来定义字符串的开头 ^ ,另一个用来定义字符串的结尾 $ 。
例子:判断下面是否是合法的xml文档。
This is bad.
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf"
xmlns:impl="http://tips.cf" xmlns:intf="http"//tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
正则表达式:<?xml.*?> 能检测到xml的标志,但是因为它能匹配到第二行xml的开头,不能作为检测xml的标准。
修改后的正则表达式:^<?xml.*?> 这样只有当xml的的开头在开头第一行才能检测到。
分行匹配模式:
前面讲过^匹配一个字符串的开头,$匹配一个字符串的结尾。但这一结论并非绝对正确,它还有一个例外或者说是一种改变这种行为的方法。
有许多正则表达式都支持使用一些特殊的元字符去改变另外一些元字符行为的做法,用来启用分行匹配模式的(?m)记号就是一个能改变其他元字符行为的元字符序列。分行匹配模式将使得正则表达式引擎把行分隔符当做一个字符串分隔符来对待。在分行匹配模式下,^不仅匹配正常的字符串开通,还将匹配行分割符(换行符)后面的开始位置。
在使用时,(?m)必须出现在整个模式的最前面,就像下面这个例子那样。
<SCRIPT>
function doSpellCheck(from , field){
//make sure not empty}
if (field.value == '')
{
return false;
}
//init
var windowName='spellwindow';
var
spellCheckURL='spell.cfm?formname=comment&fieldname='+field''
name;
...
//Done
return false;
}
正则表达式:(?m)s*//.*$ 匹配所有注释行
结果: //make sure not empty} //init //Done
注意:还有好多的正则表达式实现不支持(?m)
六:使用子表达式
子表达式的概念:在前面学习了如何匹配一个字符的连续多次重复。正如d+将匹配一个或多个数字字符,而https?://将匹配http://或https://。
在这两个例子里,事实上,是在我们此前见过的所有的例子里,用来表明重复次数的元字符(如?或*或{2},等等)只作用于紧挨着它的前一个字符或元字符。
有些短语(如Windows 2000)虽然由多个单词构成,但其实是一个整体。有许多的HTML程序员喜欢让这类短语在浏览器里显示在同一行。为了确保这一点,他们会在编写HTML文档时在这些短语的单词之间使用非换行型空格(  ; nbsp是“non-breaking space“)的缩写,其含义是”不是换行的空格“)而不是普通的空格。
例子:匹配下面文本的ip地址
Pinging hog.forta.com [12.159.46.200]
with 32 bytes of data:
正则表达式:d{1,3}.d{1,3}.d{1,3}.d{1,3}
留意d{1,3}在这个模式里重复出现了4次,它们分别匹配IP地址里的一组数字。IP地址里的4组数字有.分隔,该字符由模式里的转义序列.负责匹配。
稍微留一下就发现,在这个例子里,模式d{1,3}.(最多3个数字字符、后没跟着一个.)连续出现3次,它同样可以被表达为一个重复。
下面这个例子的另一种解决方案:
正则表达式:(d{1,3}.){1,3}d{1,3}
这个模式和上面的有着同样的结果,但我们这次试用了另一种语法:先用(和)吧表达式d{1,3}.括起来是他成为一个子表达式,再用(d{1,3}.){1,3}使这个表达式重复三次。
子表达式的嵌套
子表达式允许签到,事实上,子表达式允许多重嵌套。
如上面的获取IP的子表达式
任何一个1位或2位的数字
任何一个以1开头的3为数字。
任何一个以2开头、第2位数字在0~4之间的3位数字。
任何一个以25开头、第三位数字在0~5之间的3位数字。
正则表达式:(((d{1,2})|(1d{2})|(2[0-4]d)|(25[0-5])).){3}((d{1,2})|(1d{2})|(2[0-4]d)|(25[0-5]))