1. 概述
正则表达式原本是形式语言理论中的概念,与编译器的构造有密切的联系。但是作为一个应用软件的用户,我们没有必要去细究正则表达式的严格定义和处理方法。
我们在处理文本时,经常会遇到一些具有某种特定格式,或者说满足某种规则的文本。比如,一个无符号的整数由一连串的数字构成,而一个Email地址的格式则是“用户名@主机名”,其中用户名是一串字母或数字,主机名则是由若干个由“.”分隔的字母数字串。正则表达式就是用来指定这种规则的。如果某个字符串满足正则表达式指定的规则,则称该字符串为正则表达式的一个“匹配串”。
2. 正则表达式的构成
为了方便理解,让我们先来看看大家比较熟悉的数学表达式,“(x+3)*2+y”是一个典型的数学表达式。一个数学表达式由若干个“项”组成,“项”与“项”之间用加号或减号相连;这里“(x+3)*2”和“y”分别是两个项。每个项又由若干个“因子”组成,因子之间用乘号或除号相连;这里第一个项有两个因子“(x+3)”和“2”,而第二个项只有一个因子“y”。每个因子可以是一个简单的数,一个代数变量,也可以是放在括号里面的另一个表达式,括号中的表达式称为“子表达式”。这里“x+3”就是一个子表达式。
正则表达式的结构与数学表达式很相似。与数学表达式的“项”相对应,正则表达式由若干个“分支”构成,“分支”之间用符号“|”相连。从逻辑上讲,分支之间是一种“或”的关系,一个字符串只要与正则表达式中的任何一个分支相匹配,这个字符串就与整个正则表达式相匹配。比如,“第三人称代词”可以用正则表达式表示为“他|她|它|他们|她们|它们”。
与数学表达式的“因子”相对应,构成正则表达式“分支”的部件称为“原子”。“原子”与“原子”之间没有任何符号相连。从逻辑上讲,原子之间是串接的关系,一个字符串必须与各个原子依次相匹配,才算与这个分支相匹配。比如在上面的例子中,分支“他们”由两个原子“他”和“们”组成。
正则表达式的本质是它的“原子”可以有多种不同的形式。前面的例子是最简单的情形,即每个原子由一个普通字符组成。除此以外,“原子”还可以是特殊符号、通配符、字符集以及子表达式。
2.1 特殊符号
可以作为特殊符号的原子有:
^ 匹配行首。例如,“^他”匹配出现在行首的“他”
字。值得注意的是,这个符号仅仅表示“行首”这个位置,与它相匹配的字符串长度为0;
$ 匹配行末。与“^”相似,它仅表示“行末”这个位置。例如,“。$”匹配出现在行末的句号;
< 匹配词首。词首的定义是紧接在非字母数字之后的第一个字母数字或下划线(_),汉字永远是词首。与“^” 相似,它仅表示“词首”这个位置,匹配长度为0;
> 匹配词尾。词尾是指紧接在字母数字或下划线之后的第一个非字母数字下划线,任一汉字之后也属于词尾。词尾的匹配长度也是0;
/t TAB字符;
/e ESC字符;
2.2 通配符
通配符是用一个符号(或几个符号组合)来匹配某一类满足条件的字符。可以使用通配符来查找字符是正则表达式的一大特点。TextPro支持下列通配符(注意大小写的区别):
半角部分:
.(句点) 匹配任何字符;
/a 匹配任意英文字母;
/~a 匹配除字母外的任意字符;
/d 匹配任意数字;
/~d 匹配除数字外的任意字符;
/h 匹配任意词首字符(字母及下划线);
/~h 匹配除字母及下划线以外的任意字符;
/l 匹配任意小写字母;
/~l 匹配除小写字母外的任意字符;
/o 匹配任意八进制数字相匹配(0-7);
/~o 匹配除八进制数字外的任意字符;
/p 匹配任意半角标点符号;
/~p 匹配除半角标点以外的任意字符;
/s 匹配任意空白字符(空格、TAB);
/~s 匹配任意非空白字符;
/u 匹配任意大写字母;
/~u 匹配除大写字母外的任意字符;
/w 匹配可成词的字符(字母、数字及下划线);
/~w 匹配成词字符外的任意字符;
/x 匹配任意十六进制数字(0-9,a-f, A-F);
/~x 匹配除十六进制数字外的任意字符;
j 日文片假名
J 日文平假名
k 小写希腊字母
G 大写希腊字母
m 数学符号
S 中文序号
全角部分:
/f 匹配任意双字节字符(汉字或全角符号);
/~f 匹配任意单字节字符;
/A 匹配任意全角ASCII字符;
/b 匹配任意收录在BIG5码集中的双字节字符;
/~b 匹配未收录在BIG5码集中的双字节字符;
/c 匹配任意汉字(不包括符号);
/~c 匹配非汉字的双字节字符;
/D 匹配地支字符(子丑寅卯……);
/g 匹配收录在GB码集中的双字节字符;
/~g 匹配非收录在GB码集中的双字节字符;
/k 匹配日文片假名;
/K 匹配日文平假名;
/m 匹配小写希腊字母;
/M 匹配大写希腊字母;
/n 匹配中文数字(一二三四……);
/N 匹配大写中文数字(壹贰叁肆……);
/P 匹配全角标点符号;
/r 匹配小写俄文字母;
/R 匹配大写俄文字母;
/s 匹配数学符号;
/S 匹配中文序号(⒈⒉⒊⒋……);
/T 匹配天干字符(甲乙丙丁……);
/V 匹配竖排标点符号;
/y 匹配拼音字符;
/Y 匹配注音字符;
/Z 匹配制表字符;
2.3 字符集
字符集是用一对方括号[]括起来的字符串,用以匹配字符集中的任何一个字符。比如“[他她它]”匹配单数第三人称代词。如果方括号中的第一个字符是"^",则匹配除指定字符外的任何其它字符。在字符集中,还可以用"-"表示字符的范围,例如“[a-z]”匹配任何小写字母。注意尽量不要用“-”表示汉字的范围,因为汉字并没有公认的次序,TextPro目前是依据汉字内码来确定范围的。如果两个汉字的内码相差很大,将消耗大量的内存,运算也将非常缓慢。为了避免这种现象,TextPro中限制表示范围的起始与终止汉字必须位于同一区。如果字符集要包括字符“]”、“^”、“-”或“/”,可以在这些字符前加“/”。例如“[/^xyz]”匹配"^", "x","y"或"z"。另外需要特别指出的是,前面所述的特殊字符及通配符,除了"/t"和"/e"外,在字符集中均作为普通字符处理。
字符集的匹配速度比通配符慢,所以应该尽可能地使用通配符。例如要查找半角数字时,应该使用/d,而不要使用[0-9],虽然后者也是正确的。
2.4 子表达式
子表达式是指用一对括弧()括起来的另外一个正则表达式。使用子表达式有两种主要的目的。一是改变匹配的优先级,例如“中|西文软件”匹配的是“中”或“西文软件”,但是“(中|西)文软件”匹配的是“中文软件”或“西文软件”。
使用子表达式的另一个目的,是引用前面匹配到的内容。例如要查找形如“哈哈”、“嘻嘻”的叠字词,可以写“(/c)/1”。这里“(/c)”匹配任意汉字,而“/1”则引用匹配到的内容。TextPro允许在一个查找串包含最多9个子表达式,它们的匹配内容可以分别用“/1”,“/2”...“/9”来加以引用。子表达式也可以嵌套另一个子表达式,子表达式左括号出现的序号为这个表达式的编号。另外需要注意的是,只能引用已经匹配了的子表达式,象上面的例子不可以写成“/1(/c)”,同理,也不应该引用不同分支中的子表达式,因为一个正则表达式中只可能有一个分支被匹配。
2.5 重复指示符
正则表达式的另外一个强大的功能是重复匹配的能力。前述的任何一种“原子”之后,都可以指定一个重复指示符。下面列出各种重复指示符:
? 表示前一“原子”可有可无(重复0或1次)。例如“我们?”匹配“我”或“我们”;
+ 表示前一“原子”至少匹配一次。例如“/d+”匹配任何一个无符号整数;
* 表示前一“原子”重复匹配0或多次。例如“/h/w*”表示许多高级语言对“变量”的定义:以字母或下划线开头,后接任意多个字母数字或下划线;
{n} 表示前一“原子”重复匹配n次。例如“/c啦{3}”匹配“哗啦啦啦”或“呼啦啦啦”等;
{n,m} 表示前一“原子”重复匹配n至m次,其中n<=m。如果n>m,TextPro将自动交换m与n的值;
{n,} 至少重复匹配n次,相当于{n,无穷大};
{,m} 至多重复匹配m次,相当于{0,m};
{} 重复任意多次,相当于*。
在前面所述的各种重复指示符中,如果重复的次数不定,TextPro将匹配尽可能长的目标串(但最多不超过32767次,这是TextPro内设定的上限)。例如有一字符串“你好,我好,大家好”,表达式“你.*好”将匹配整个字符串,而不是“你好”或“你好,我好”。如果需要匹配尽可能短的目标串,可以采用前述的最后四种形式,并在“{”之后加上“-”号。上例中的表达式如改为“你.{-}好”,则匹配串为“你好”。
{-n,m} 重复匹配m至n次,匹配次数尽可能少;
{-n,} 至少重复匹配n次,匹配次数尽可能少;
{-,m} 至多重复匹配m次,匹配次数尽可能少,相当于{-0,m};
{-} 重复任意多次,类似于*,但匹配次数尽可能少。
重复指示符只对紧邻在其前的“原子”起作用,例如“你好+”将匹配“你好”,“你好好”……。但是不会匹配“你好你好”。如果要重复匹配一组原子,可以使用括号(子表达式),如“(你好)+”就会匹配“你好你好”。
需要指出的是,重复指示符与引用子表达式具有不同的含义。重复指示符是重复“匹配”,至于匹配的内容则可以不同;而引用子表达式则是重复匹配的内容。例如,“/d{2}”可以匹配任何一个两位数的整数,但是“(/d)/1”只能匹配“11”、“22”、“33”等数字相同两位数。当然,也可以重复引用子表达式,如“(/d)/1*”可以匹配“2”,“33”、“111”等各位数全同的整数。
如前所述,在正则表达式中,以下字符“*?+.()[]{}/”具有特殊的含义。如果需要查找这些字符本身,可以在该字符前加一个反斜杠“/”。例如查“/def”可以输入“//def”。
3. 替换表达式
3.1 特殊字符
在进行替换时,也可以在替换串中使用一些特殊字符。目前TextPro支持的特殊字符有:
/n 插入回车符。可以用这个字符把某些行分成两行或多行;
/b 向前删除一个字符。当这个字符位于替换串之首时,将删除匹配串之前的一个字符。若匹配串位于行首,将使匹配串所在行与前一行相合并;
/d 向后删除一个字符。当这个字符位于替换串之末时,将删除匹配串之后的一个字符。若匹配串位于行末,将使匹配串所在行与下一行相合并;
/e 插入一个ESC字符;
/t 插入一个TAB字符;
也可以在替换串中引用查找串中的匹配到的子表达式。引用方法也是用“/1”、“/2”等。另外还可以用“/0”或“&”来引用整个匹配到的字符串。
3.2 替换函数
在替换串中还可以使用一组替换函数,来对查找到的内容做某种变换。替换函数的形式是/f{...},其中“f”是函数名,它是一个半角英文字母。花括号中的内容是函数的参数。例如,/u{a}表示把“a”转换为大写。目前TextPro支持三个替换函数,在后继版本中逐步增加。
/u 转换为大写
/l 转换为小写
/U 首字母大写
替换函数的参数部分可以略去不写。如果略去,默认的参数是查找到的内容,即/0。例如,要把文中所有英文单词的首字母大写,可以查找“</a+>”,并替换为“/U{/0}”,替换串也可以简写为“/U”
4. 自定义替换功能
TextPro 4.5提供了自定义替换功能。所谓自定义替换,其实是一张替换表,它把某个字符串对应转换为另外一个字符串,比如把汉字转换为拼音。
替换表是一个文本文件,它的每一行指定一个转换关系。行由两栏组成,栏与栏之间用一个(或多个)空格(或TAB)分开。第一栏是源字符串,第二栏是目标字符串。如果源串或目标串中需要包含空格,可以把串用半角的单引号或双引号括起来。例如把汉字转为拼音的自定义替换表可以这样写
中 zhong1
国 "guo2"
大 da4
...
替换表中的最好不要有重复的源串,如有重复,TextPro只取最后出现的那对转换关系。
替换表准备好后,选择菜单“设置|自定义替换表”来设置替换表。TextPro允许定义多达10张替换表。首先选择一个位置,使那一行被选中,然后按“文件”按钮,即可装入这张替换表。你也可以为这张替换表起个名字,按“命名”按钮可以输入名称。“过滤”按钮与替换函数有关,等一下再作介绍。设置完以后,按“退出”钮结束。
现在,选择菜单“编辑|自定义替换”,可以看到弹出的下级菜单中有一项功能被开启了,菜单项的名称就是刚才给替换表起的名称(如果没有起名称,默认的菜单名称是“自定义替换n”)。选择这项功能,将把出现在当前文件中的所有源串按替换表替换为目标串。
4.1 在查找/替换中使用自定义替换表
有的时候,上述简单的自定义替换功能是不够的。例如,用户可能希望只把出现在括号内的源串替换为目标串。这种文本处理可以通过在查找/替换中使用自定义替换表来解决。
在查找/替换功能中使用自定义替换表的替换函数是/Tn,其中n是0-9的数字, 注意n为0表示第10张替换表。如果略去n,其效果相当于/T1,即使用第一张替换表。例如要把所有放在方括号中的汉字替换为拼音,可以查找“/[(/c)/]”,替换为“/T{/1}”。即把第一个子表达式的匹配内容按自定义替换表转换。注意,如果/T函数的参数不在替换表的源串中,/T函数的结果与源串相同,即不做任何变换。
有些情况下,用户可能希望只使用替换表的一部分内容。还是以拼音为例,前面给出的替换表中包含了拼音的音调,如果在替换时不希望加上这些音调数字,可以使用“过滤”功能。所谓过滤,其实是用一个正则表达式去分析替换表的目标串,并把其中的某个子表达式取出来。
使用“过滤”时,在“设置自定义替换表”对话框中,点“过滤”按钮,在弹出的对话框中填入一个正则表达式。再以拼音为例,表达式可以写为“(/a+)(/d?)”,其中第一对括号中的是不含音调的拼音,第二对括号是音调。在调用/T函数时,TextPro会在目标串中查找这个正则表达式。但是如何把其中的子表达式取出来呢?/T函数还有一个可选的下标,取第n个子表达式的值就写作/T{...}[n]。所以,把放在方括号中的汉字替换为不带调的拼音,可以查找“/[(/c)/]”,替换为“/T{/1}[1]”
5. 应用举例
例一:在TextPro的制作过程中,我们需要整理许多资料。例如简转繁的资料是一个文本文件,每行两个汉字,前一个为简体字,后一个为繁体字。但是有不少行简繁体其实是同一个字,我们希望将其剔除。
操作办法:用替换功能,在“查找”中输入“(/c)/1”,在替换中输入“/d”。
分析:“/c”匹配任一汉字,“/1”是引用子表达式,因此上面的正则表达式表示查找连续两个相同的汉字。在替换时输入“/d”,表示将找到的两个汉字替换成空串,并删除下一个字符。由于文件中每行只有两个汉字,删除下一个字符其实就删掉了行末的回车符,其结果把这些无用的行全部清除。
例二:某文件由一些有用的资料及注释组成。注释单独成行,并以“#”开头。现在希望将所有的注释行删除。
操作办法:用替换功能,在“查找”中输入“^#.*$”,在替换在输入“/d”。
分析:^匹配行首,^#表示行首有符号#,.*匹配#之后的所有字符,直到行末($)。这个表达式将整行匹配所有以#开头的行。替换成“/d”将把这些行清除。
例三:有一个从“输入法生成器”反编译出来的拼音表,其中有单字的拼音,也有词组的拼音。现在希望把单字的拼音和词组的拼音分开。已经文件的格式是每行一个字或词组,行首是汉字或词组,其后紧跟拼音。
操作办法:用替换功能,查找“^/c/c+/~f+”,替换为“/d”,就得到了一份单字的拼音表,另存为“单字.txt”后,按Ctrl+Z(UNDO)撤消刚才的操作,再用替换功能,查找“^/c/~f+”,替换为“/d”,就得到了词组的拼音表,可另存为“词组.txt”。
分析:“/c/c+/~f+”匹配行首以汉字开头,跟着一个以上的汉字,再跟着一个以上任意半角字符的行,也就是所有的词组行,替换为“/d”把这些行删除,得到的是单字的拼音表;“^/c/~f+”匹配以一个汉字开头,紧跟着一个以上任意半角字符,这些正好是单字的拼音行,删除后即得词组的拼音表。
例四:组字符转GBK汉字。有些文本中使用一种组字规则来表示某些罕用的汉字,如用“[門@(人/(人*人))]”表示“閦”。这些汉字大部分收在GBK字符集中,现在希望将它们转换成相应的GBK汉字。
这项工作可以用自定义替换来完成。先准备一份组字规则表,例如TextPro中就附带了这样一份转换表,现有461个组字。在“设置自定义替换表”中,将此表装入,可命名为“组字符转GBK汉字”。然后分两步完成:
1、查找/[(.{-1,})/],替换为[/T{/1}]。结果分为两种,第一种如[閦],第二种如[合*牛]。
2、查找/[(/c)/],替换为/1. 这样对第一种可去掉括号,而第二种可保持原样。
例五:汉字注拼音。有一份文本,现在要给每个汉字注上拼音,格式为
中(zhong阴平) 国(guo阳平) 人(ren阳平)...
我们可能用自定义替换来解决这个问题。需要用到两张自定义替换表。第一张是拼音表,其格式为
中 zhong1
国 guo2
人 ren2
....
另一张表是音调名称,一共5行
1 阴平
2 阳平
3 上声
4 去声
5 轻声
在“设置自定义替换表”中,把拼音表设为第一张替换表,并输入“过滤”表达式“(/a+)(/d)”;再把音调表设置为第二张替换表。
好了,现在查找“/c”,替换为“/0(/T[1]/T2{/T[2]})”即可完成注音工作。
分析:替换串的第一个“/0”表示把这个汉字再写一遍,括号里的“/T[1]”相当于“/T1{/0}[1]”,它从第一张表中查找匹配到的汉字,并把对应的拼音用过滤表达式做一次查找,取查找结果的第一个子表达式;“/T2{/T[2]}”是一个嵌套的替换函数调用,内层的“/T[2]”是取音调数字,然后再以这个音调数字为参数,查找第二张替换表,得到该音调的中文表示。
总而言之,正则表达式和自定义替换是两项非常有用的功能,经过适当的组合,可以完成的功能几乎是无限的。
C#正则表达式应用实例
两种使用方法:
1、在文本输入框后加入正则表达式验证控件Regularexpression_r_rValidator。此种方法适用于WebForm中。
在Validationexpression_r_r选项中,输入验证规则。
在ControlToValidate选项中,选择要验证的控件。
在ErrorMesage选项中,输入如果验证没有通过页面要显示的信息。
2、在隐藏代码中使用,此方法适用于WinForm和WebForm中。
这种方法要先加入声明命名空间:
using System.Text.Regularexpression_r_rs;
然后在方法中声明验证规则:
string s_reg = @"^/d+$";
声明要验证的字符串:
string s = textBox1.Text;
新建一个实例,并将验证规则以参数形式传入实例,初始化类:
Regex reg = new Regex( s_reg );
然后拿实例对要验证的字符串进行验证,返回结果为bool值:
if ( reg.IsMatch (s) )
{
MessageBox.Show( "It 's OK~");
}
else
{
MessageBox.Show( "It 's Bad~");
}
正则表达式的一些示例::
C#中正则表达式 (一)
1.匹配HTML标记的正则表达式:<(.*)>.*<///1>|<(.*) //> 例如:<title></title>
2. 正整数: ^[0-9]*[1-9][0-9]*$
3.负整数: ^-[0-9]*[1-9][0-9]*$
4.整数: -?/d+$
5.正浮点数: ^(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*))$
6.负浮点数: ^(-(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*)))$
7.浮点数:^(-?/d+)(/./d+)?$
8.26个英文字(不区分大小写): ^[A-Za-z]+$
9.26个大写英文字母: ^[A-Z]+$
10.26个小写英文字母:^[a-z]+$
11.数字和26个英文字母混合: ^[A-Za-z0-9]+$
12.数字和26个英文字母和下划线混合: ^/w+$
13.电子邮件地址: /w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)*h
14.网址URL: ^[a-zA-z]+://(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$
15.中国电话: ((d{3,4})|d{3,4}-)?d{7,8}(-d{3})* 例如:021-8888888 或者0515-88888888 或者 021-88888888-888
16.字母开头,允许5-16字节,允许字母数字下划线: ^[a-zA-Z][a-zA-Z0-9_]{6,20}$
17.QQ号: ^[1-9]*[1-9][0-9]*$
18.IP地址: ^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0
-5])$
19.首尾空格:(^/s*)|(/s*$)
20.空行:/n[/s| ]*/r
21.中国邮政编码:[1-9]/d{5}(?!/d)
22. 中国手机:(86)*0*13/d{9}
23.中国电话(包括手机):(/(/d{3,4}/)|/d{3,4}-|/s)?/d{7,14}
24.数字:(-?/d*)(/./d+)?
25.双字节字符:[^/x00-/xff]*
26.过滤不安全的字符:^(([A-Z]*|[a-z]*|/d*|[-_/~!@#/$%/^&/*/./(/)/[/]/{/}<>/?/////'/"]*)|.{0,5})$|/s
27.日期:((((19){1}|(20){1})d{2})|d{2})[01]{1}d{1}[0-3]{1}d{1} 如:20060518
C#中正则表达式 (二)
只能输入数字:"^[0-9]*$"。
只能输入n位的数字:"^/d{n}$"。
只能输入至少n位的数字:"^/d{n,}$"。
只能输入m~n位的数字:。"^/d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
只能输入非零的正整数:"^/+?[1-9][0-9]*$"。
只能输入非零的负整数:"^/-[1-9][]0-9"*$。
只能输入长度为3的字符:"^.{3}$"。
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:"^/w+$"。
验证用户密码:"^[a-zA-Z]/w{5, }$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&’,;=?$/"等字符:"[^%&’,;=?$/x22]+"。
只能输入汉字:"^[/一-/龥]{0,}$"
验证Email地址:"^/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)*$"。
验证InternetURL:"^http://([/w-]+/.)+[/w-]+(/[/w-./?%&=]*)?$"。
验证电话号码:"^(/(/d{3,4}-)|/d{3.4}-)?/d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
验证身份证号(15位或18位数字):"^/d{15}|/d{18}$"。
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:onkeyup="val=val.replace(/[^/一-/龥]/g,’’)" onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^/一-/龥]/g,’’))"
用正则表达式限制只能输入全角字符: onkeyup="val=val.replace(/[^/?-/?]/g,’’)" onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^/?-/?]/g,’’))"
用正则表达式限制只能输入数字:onkeyup="val=val.replace(/[^/d]/g,’’) "onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^/d]/g,’’))"
用正则表达式限制只能输入数字和英文:onkeyup="val=val.replace(/[/W]/g,’’) "onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^/d]/g,’’))"
得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1
以下是引用片段:
s="http://www.111.com/test.htm"
s=s.replace(/(.*//){0,}([^/.]+).*/ig,"$2")
alert(s)
匹配双字节字符(包括汉字在内):[^/x00-/xff]
应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
以下是引用片段:
String.prototype.len=function(){return this.replace([^/x00-/xff]/g,"aa").length;}
匹配空行的正则表达式:/n[/s| ]*/r
匹配HTML标记的正则表达式:/<(.*)>.*<///1>|<(.*) //>/
匹配首尾空格的正则表达式:(^/s*)|(/s*$)
以下是引用片段:
String.prototype.trim = function()
{
return this.replace(/(^/s*)|(/s*$)/g, "");
}
利用正则表达式分解和转换IP地址:
下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:
以下是引用片段:
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!")
}
}
正则表达式基础知识
一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。如:
JScript VBScript 匹配
/^/[ /t]*$/ "^/[ /t]*$" 匹配一个空白行。
//d{2}-/d{5}/ "/d{2}-/d{5}" 验证一个ID 号码是否由一个2位数字,一个连字符以及一个5位数字组成。
/<(.*)>.*<///1>/ "<(.*)>.*<///1>" 匹配一个 HTML 标记。
下表是元字符及其在正则表达式上下文中的行为的一个完整列表:
字符 描述
/ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'/n' 匹配一个换行符。序列 '//' 匹配 "/" 而 "/(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^ 也匹配 '/n' 或 '/r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$ 也匹配 '/n' 或 '/r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n是一个非负整数。匹配确定的n次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n是一个非负整数。至少匹配n次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "/n" 之外的任何单个字符。要匹配包括 '/n' 在内的任何字符,请使用象 '[./n]' 的模式。
(pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用S Matches集合,在JScript 中则使用$0…$9属性。要匹配圆括号字符,请使用 '/(' 或 '/)'。
(?:pattern) 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配x或y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
/b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er/b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
/B 匹配非单词边界。'er/B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
/cx 匹配由x指明的控制字符。例如, /cM 匹配一个 Control-M 或回车符。x的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
/d 匹配一个数字字符。等价于 [0-9]。
/D 匹配一个非数字字符。等价于 [^0-9]。
/f 匹配一个换页符。等价于 /x0c 和 /cL。
/n 匹配一个换行符。等价于 /x0a 和 /cJ。
/r 匹配一个回车符。等价于 /x0d 和 /cM。
/s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ /f/n/r/t/v]。
/S 匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。
/t 匹配一个制表符。等价于 /x09 和 /cI。
/v 匹配一个垂直制表符。等价于 /x0b 和 /cK。
/w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
/W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
/xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'/x41' 匹配 "A"。'/x041' 则等价于 '/x04' & "1"。正则表达式中可以使用 ASCII 编码。.
/num 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,'(.)/1' 匹配两个连续的相同字符。
/n 标识一个八进制转义值或一个向后引用。如果 /n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字 (0-7),则n为一个八进制转义值。
/nm 标识一个八进制转义值或一个向后引用。如果 /nm之前至少有nm个获得子表达式,则nm为向后引用。如果 /nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字 (0-7),则 /nm将匹配八进制转义值nm。
/nml 如果n为八进制数字 (0-3),且m和l均为八进制数字 (0-7),则匹配八进制转义值nml。
/un 匹配n,其中n是一个用四个十六进制数字表示的 Unicode 字符。例如, /? 匹配版权符号 (?)。
下面看几个例子:
"^The":表示所有以"The"开始的字符串("There","The cat"等);
"of despair$":表示所以以"of despair"结尾的字符串;
"^abc$":表示开始和结尾都是"abc"的字符串——呵呵,只有"abc"自己了;
"notice":表示任何包含"notice"的字符串。
'*','+'和'?'这三个符号,表示一个或一序列字符重复出现的次数。它们分别表示“没有或
更多”,“一次或更多”还有“没有或一次”。下面是几个例子:
"ab*":表示一个字符串有一个a后面跟着零个或若干个b。("a", "ab", "abbb",……);
"ab+":表示一个字符串有一个a后面跟着至少一个b或者更多;
"ab?":表示一个字符串有一个a后面跟着零个或者一个b;
"a?b+$":表示在字符串的末尾有零个或一个a跟着一个或几个b。
也可以使用范围,用大括号括起,用以表示重复次数的范围。
"ab{2}":表示一个字符串有一个a跟着2个b("abb");
"ab{2,}":表示一个字符串有一个a跟着至少2个b;
"ab{3,5}":表示一个字符串有一个a跟着3到5个b。
请注意,你必须指定范围的下限(如:"{0,2}"而不是"{,2}")。还有,你可能注意到了,'*','+'和
'?'相当于"{0,}","{1,}"和"{0,1}"。
还有一个'|',表示“或”操作:
"hi|hello":表示一个字符串里有"hi"或者"hello";
"(b|cd)ef":表示"bef"或"cdef";
"(a|b)*c":表示一串"a""b"混合的字符串后面跟一个"c";
'.'可以替代任何字符:
"a.[0-9]":表示一个字符串有一个"a"后面跟着一个任意字符和一个数字;
"^.{3}$":表示有任意三个字符的字符串(长度为3个字符);
方括号表示某些字符允许在一个字符串中的某一特定位置出现:
"[ab]":表示一个字符串有一个"a"或"b"(相当于"a|b");
"[a-d]":表示一个字符串包含小写的'a'到'd'中的一个(相当于"a|b|c|d"或者"[abcd]");
"^[a-zA-Z]":表示一个以字母开头的字符串;
"[0-9]%":表示一个百分号前有一位的数字;
",[a-zA-Z0-9]$":表示一个字符串以一个逗号后面跟着一个字母或数字结束。
你也可以在方括号里用'^'表示不希望出现的字符,'^'应在方括号里的第一位。(如:"%[^a-zA-Z]%"表示两个百分号中不应该出现字母)。
为了逐字表达,必须在"^.$()|*+?{/"这些字符前加上转移字符'/'。
请注意在方括号中,不需要转义字符。