正则表达式分析网页数据

本文深入探讨Python中正则表达式的使用,包括基础概念、语法、应用实例及高级功能,帮助开发者掌握正则表达式的高效操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

本文介绍了Python对于正则表达式的支持,包括正则表达式基础以及Python正则表达式标准库的完整介绍及使用示例。本文的内容不包括如何编写高效的正则表达式、如何优化正则表达式,这些主题请查看其他教程。

注意:本文基于Python2.4完成;如果看到不明白的词汇请记得百度谷歌或维基,whatever。

尊重作者的劳动,转载请注明作者及原文地址 >.<html

1. 正则表达式基础

1.1. 简单介绍

正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同;但不用担心,不被支持的语法通常是不常用的部分。如果已经在其他语言里使用过正则表达式,只需要简单看一看就可以上手了。

下图展示了使用正则表达式进行匹配的流程: 
re_simple

正则表达式的大致匹配过程是:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。如果表达式中有量词或边界,这个过程会稍微有一些不同,但也是很好理解的,看下图中的示例以及自己多使用几次就能明白。

下图列出了Python支持的正则表达式元字符和语法:   
pyre

1.2. 数量词的贪婪模式与非贪婪模式

正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。

1.3. 反斜杠的困扰

与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

1.4. 匹配模式

正则表达式提供了一些可用的匹配模式,比如忽略大小写、多行匹配等,这部分内容将在Pattern类的工厂方法re.compile(pattern[, flags])中一起介绍。

2. re模块

2.1. 开始使用re

Python通过re模块提供对正则表达式的支持。使用re的一般步骤是先将正则表达式的字符串形式编译为Pattern实例,然后使用Pattern实例处理文本并获得匹配结果(一个Match实例),最后使用Match实例获得信息,进行其他的操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# encoding: UTF-8
import  re
 
# 将正则表达式编译成Pattern对象
pattern =  re. compile (r 'hello' )
 
# 使用Pattern匹配文本,获得匹配结果,无法匹配时将返回None
match =  pattern.match( 'hello world!' )
 
if  match:
     # 使用Match获得分组信息
     print  match.group()
 
### 输出 ###
# hello

re.compile(strPattern[, flag]):

这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。 第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M。另外,你也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的。 
可选值有:

  • re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
  • M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
  • S(DOTALL): 点任意匹配模式,改变'.'的行为
  • L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
  • U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
  • X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
?
1
2
3
4
a =  re. compile (r """\d +  # the integral part
                    \.    # the decimal point
                    \d *  # some fractional digits""" , re.X)
b =  re. compile (r "\d+\.\d*" )

re提供了众多模块方法用于完成正则表达式的功能。这些方法可以使用Pattern实例的相应方法替代,唯一的好处是少写一行re.compile()代码,但同时也无法复用编译后的Pattern对象。这些方法将在Pattern类的实例方法部分一起介绍。如上面这个例子可以简写为:

?
1
2
m =  re.match(r 'hello' , 'hello world!' )
print  m.group()

re模块还提供了一个方法escape(string),用于将string中的正则表达式元字符如*/+/?等之前加上转义符再返回,在需要大量匹配元字符时有那么一点用。

2.2. Match(Match只找到一次可匹配的结果即返回

Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。

属性:

  1. string: 匹配时使用的文本。
  2. re: 匹配时使用的Pattern对象。
  3. pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
  4. endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
  5. lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
  6. lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。

方法:

  1. group([group1, …]): 
    获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
  2. groups([default]): 
    以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
  3. groupdict([default]): 
    返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
  4. start([group]): 
    返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
  5. end([group]): 
    返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
  6. span([group]): 
    返回(start(group), end(group))。
  7. expand(template): 
    将匹配到的分组代入template中然后返回。template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。\id与\g<id>是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import  re
m =  re.match(r '(\w+) (\w+)(?P<sign>.*)' , 'hello world!' )
 
print  "m.string:" , m.string
print  "m.re:" , m.re
print  "m.pos:" , m.pos
print  "m.endpos:" , m.endpos
print  "m.lastindex:" , m.lastindex
print  "m.lastgroup:" , m.lastgroup
 
print  "m.group(1,2):" , m.group( 1 , 2 )
print  "m.groups():" , m.groups()
print  "m.groupdict():" , m.groupdict()
print  "m.start(2):" , m.start( 2 )
print  "m.end(2):" , m.end( 2 )
print  "m.span(2):" , m.span( 2 )
print  r "m.expand(r'\2 \1\3'):" , m.expand(r '\2 \1\3' )
 
### output ###
# m.string: hello world!
# m.re: <_sre.SRE_Pattern object at 0x016E1A38>
# m.pos: 0
# m.endpos: 12
# m.lastindex: 3
# m.lastgroup: sign
# m.group(1,2): ('hello', 'world')
# m.groups(): ('hello', 'world', '!')
# m.groupdict(): {'sign': '!'}
# m.start(2): 6
# m.end(2): 11
# m.span(2): (6, 11)
# m.expand(r'\2 \1\3'): world hello!

2.3. Pattern

Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找。

Pattern不能直接实例化,必须使用re.compile()进行构造。

Pattern提供了几个可读属性用于获取表达式的相关信息:

  1. pattern: 编译时用的表达式字符串。
  2. flags: 编译时用的匹配模式。数字形式。
  3. groups: 表达式中分组的数量。
  4. groupindex: 以表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
import  re
p =  re. compile (r '(\w+) (\w+)(?P<sign>.*)' , re.DOTALL)
 
print  "p.pattern:" , p.pattern
print  "p.flags:" , p.flags
print  "p.groups:" , p.groups
print  "p.groupindex:" , p.groupindex
 
### output ###
# p.pattern: (\w+) (\w+)(?P<sign>.*)
# p.flags: 16
# p.groups: 3
# p.groupindex: {'sign': 3}

实例方法[ | re模块方法]:

  1. match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]): Match只找到一次可匹配的结果即返回

    这个方法将从string的pos下标处起尝试匹配pattern;如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。 
    pos和endpos的默认值分别为0和len(string);re.match()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。 
    注意:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'。 
    示例参见2.1小节。
  2. search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]): (只要有一次匹配时,即返回匹配对象
    这个方法用于查找字符串中可以匹配成功的子串。从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象;若无法匹配,则将pos加1后重新尝试匹配;直到pos=endpos时仍无法匹配则返回None。 
    pos和endpos的默认值分别为0和len(string));re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。 
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # encoding: UTF-8
    import  re
     
    # 将正则表达式编译成Pattern对象
    pattern =  re. compile (r 'world' )
     
    # 使用search()查找匹配的子串,不存在能匹配的子串时将返回None
    # 这个例子中使用match()无法成功匹配
    match =  pattern.search( 'hello world!' )
     
    if  match:
         # 使用Match获得分组信息
         print  match.group()
     
    ### 输出 ###
    # world
  3. split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]): 
    按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。 
    ?
    1
    2
    3
    4
    5
    6
    7
    import  re
     
    p =  re. compile (r '\d+' )
    print  p.split( 'one1two2three3four4' )
     
    ### output ###
    # ['one', 'two', 'three', 'four', '']
  4. findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]): 
    搜索string,以列表形式返回全部能匹配的子串。 该函数需要找到所有可匹配的对象,并返回。
    ?
    1
    2
    3
    4
    5
    6
    7
    import  re
     
    p =  re. compile (r '\d+' )
    print  p.findall( 'one1two2three3four4' )
     
    ### output ###
    # ['1', '2', '3', '4']
  5. finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]): 
    搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。 
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    import  re
     
    p =  re. compile (r '\d+' )
    for  m in  p.finditer( 'one1two2three3four4' ):
         print  m.group(),
     
    ### output ###
    # 1 2 3 4
  6. sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]): 
    使用repl替换string中每一个匹配的子串后返回替换后的字符串。 
    当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。 
    当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。 
    count用于指定最多替换次数,不指定时全部替换。 
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import  re
     
    p =  re. compile (r '(\w+) (\w+)' )
    s =  'i say, hello world!'
     
    print  p.sub(r '\2 \1' , s)
     
    def  func(m):
         return  m.group( 1 ).title() +  ' '  +  m.group( 2 ).title()
     
    print  p.sub(func, s)
     
    ### output ###
    # say i, world hello!
    # I Say, Hello World!
  7. subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]): 
    返回 (sub(repl, string[, count]), 替换次数)。 
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import  re
     
    p =  re. compile (r '(\w+) (\w+)' )
    s =  'i say, hello world!'
     
    print  p.subn(r '\2 \1' , s)
     
    def  func(m):
         return  m.group( 1 ).title() +  ' '  +  m.group( 2 ).title()
     
    print  p.subn(func, s)
     
    ### output ###
    # ('say i, world hello!', 2)
    # ('I Say, Hello World!', 2)

以上就是Python对于正则表达式的支持。熟练掌握正则表达式是每一个程序员必须具备的技能,这年头没有不与字符串打交道的程序了。笔者也处于初级阶段,与君共勉,^_^

另外,图中的特殊构造部分没有举出例子,用到这些的正则表达式是具有一定难度的。有兴趣可以思考一下,如何匹配不是以abc开头的单词,^_^

全文结束



正则表达式的语法:


1.正则表达式简介

正则表达式(Regular expression,简写为Regexes)是一种用来操作和检验字符串数据的强大工具。它相当与一串特殊的字符,用它可以转换成算法,对文本进行匹配等操作。

事实上正则表达式有其自身的一套语法,这种语法对于初学者来说显得有些晦涩难懂。尤其是其构造比较困难,称为很多入门者的障碍。但当掌握后却可以轻易的解决以前不容易解决的很多文本类问题,如验证提取等。

其常用场合有如下三种:

Ø 测试字符串的某个模式。例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。

Ø 替换文本。可以在文档中使用一个正则表达式来标识特定文字,然后可以全部将其删除,或者替换为别的文字。

Ø 根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。

2.正则表达式基础语法

2.1匹配不同类型的字符

字符类

匹配的字符

\d

匹配一个数字字符。等价于 [0-9]

\D

匹配一个非数字字符。等价于 [^0-9]

\w

匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'

\W

匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'

\s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]

\S

匹配任何非空白字符。等价于 [^ \f\n\r\t\v]

.(点号)

任一字符

[...]

括号中的任一字符

[^…]

非括号中的任一字符

2.2定位控制字符

^

其后的模式必须在字符串的开始处,如果是多行则在任一行的开始C#需要设定Multiline标志

$

前面的模式必须在一行的末尾,如果是多行,则在任意行的末尾

\A

前面的模式必须在字符串的开始处;多行标志被忽略

\z

前面的模式必须在字符串的末尾处,多行标志被忽略

\Z

前面的模式必须位于字符串的末尾或位于换行符前

\b

匹配一个单词字符的开始,单词字符是[a-zA-Z0-9]中的一位

\B

匹配一个非单词边界的位置, 不在一个单词的开始

2.3指定重复字符

{n}

匹配前面的字符n

{n,}

匹配前面的字符最少n

{n,m}

匹配前面的字符nm

?

匹配前面的字符0次或1

+

匹配前面的字符至少1

*

匹配前面的字符至少0

2.4特殊控制类

|

指定字符替换,即该位置可以是|两边的任一个表达式

2.5 特殊字符转义序列

\\

匹配”\”

\.

匹配“.

\*

匹配“*

\(

匹配“(”

\)

匹配”)”

\?

匹配“?“

\+

匹配“+

\|

匹配“|

\{

匹配“{

\}

匹配“}

\^

匹配“^

\$

匹配“$

\n

匹配换行符

\r

匹配回车

\t

匹配Tab

\v

匹配垂直制表符

\f

匹配换页符

\nnn

匹配一个三位八进制数指定的ASCII字符,如\103匹配C

\xnn

匹配一个二位16进制数指定的ASCII字符,例如\x43匹配C

\unnnn

匹配一个416进制数指定的Unicode字符

\cV

匹配一个控制字符,(如复制Ctrl+C

2.6正则表达式分组、替换、反向引用等高级应用

以上只是正则表达式的基础部分,从这里开始才算真正开始正则表达式之旅。

² 分组

分组技术可以匹配在一个组中的所有字符,用()来表示,是下面两个技术的基础所在。“()“又称捕获符号。

1. 捕获:()

例子:ABC1EDF2UU

匹配组表达式:([A-Z]{3})\d --匹配3个连续大写字母和一个数字

匹配结果:1.ABC1,2.EDF2

如果用C#中的group,则为ABC,EDF。因为group搜集的是匹配组的内容。
2.
非捕获(?:)

使用了非捕获就说明该()中的内容将不作为捕获的组返回,而和其它表达式共同构成匹配项返回。也就是捕获组将不存在。

例:1AF3EDC

匹配表达式:(?:\d|[A-Z]\w --匹配一个数字或字母加一个任意的字符。

匹配结果:1.1A 2.F3 3.ED

没有组被捕获

2. 通过名称捕获(?<name>

定义了名称捕获的组可以在反向匹配中运用名称进行反向引用而不需要再使用数字进行反向捕获。注意组名区分大小写!

² 替换

替换,顾名思义,是将匹配的字符替换成其他指定的字符形式。这个功能是在分组的基础上的(当然或许可以单独存在,但是那样匹配的功能显然不够强大)。在这里有一个技巧是使用附加的匹配字符控制匹配内容。

$group

group指定的组号进行替换

${name}

替换由<?name>匹配的最后一个子串

$$

替换字符$

$&

替换整个的匹配

$+

替换最后捕获的组

$

替换整个输入的字符串

² 反向引用

反向匹配可以引用前面组中的匹配形式。“\匹配组的数字表示(1为基数)“或者”\k<groupname>

² 高级组

1. 正声明(?=

规定了括号中的模式必须出现在声明的右侧。模式将不构成匹配的一部分。

2. 负声明(?!

规定了括号中的模式不能出现在声明的右侧,模式将不构成匹配的一部分。

3. 反向正声明(?<=

规定了括号中的模式必须出现在声明的左侧,模式将不构成匹配的一部分。

4. 反向负声明(?<!

规定了括号中的模式必须出现在声明的左侧。模式不构成匹配的一部分。

5. 非回溯(?>

防止了正则表达式引擎搜索失败时回溯,这称之为贪婪的子表达式。

如输入字符串:He was very trusting.

正则表达式:.*ing将匹配trusting但是如果加入(?>ing则不能完成匹配。

非回溯组也是非捕获组。他对于提高正则表达式的效率很有效。

如匹配一个www.****.com的网址。使用www\.(.*)\.com显然要比www\.([^.]*)\.com效率要低的多,因为前者必须使用组中的回溯操作,回溯是很艰难的过程,所以当使用非回溯的正则表达式时时可以显著提高正则表达式的效率的。

其实正则表达式是只注重匹配结果的,所以会努力去匹配所存在的字符串。这就是它的贪婪性所在。(这点其实理解的不是太深)。

注意以上这些(1-5)都不能够用于反向引用,因为以上声明将不作为匹配的一部分。

2.7在正则表达式中做决策

高级决策的两种写法:

1=>(?(expressionyes|no)

2=>(?(?=expression)yes|no)

这两种方式中的的expression匹配则后面进行匹配yes,否则匹配no

需要注意的一点是yes测试和决策测试是在同一个起点里进行的。

如以下字符串:77-77A 69-AA 57-B

匹配表达式为:(\d7)?-(?(1)\d\d[A-Z]|[A-Z][A-Z])

匹配结果为:

1.77-77A 2. –AA

这个正则表达式中用到了引用组,(?(1**)中的1也可以换为\1,这样不影响匹配。这个匹配中如果将决策后面的\d\d去掉则会出现不同的结果,这时只会有一个-AA是匹配的。因为决策点和yes表达式是从同一个起点开始匹配所以即使决策点匹配了,但是后面的yes表达式仍然不匹配。就只匹配no部分的表达式。最终结果也必然改变,理解这一点很重要。

2.8 正则表达式的选项

快到结尾了,再说下正则表达式的选项。选项其实就是将正则表达式的设置改到组中来。如(?i:[a-z])将忽略大小写进行匹配。实际上如果学过Javascript中的正则表达式,可以看出这个ijavascript中表示的还是这个意思。

N

规定只有显示命名的组标号的组才能有效的捕获

I

此选项匹配不区分大小写的匹配

X

此选项规定,非转义的空字符被排除在模式之外,并启用了一个前缀#的注释

M

指定多行模式,修改了^$的定义

S

指定单行模式

2.9正则表达式的规则

1.正则表达式会对输入字符传进行最快的匹配,它一次搜索一个字符,知道实现第一次匹配。

2.发现一个匹配的开始后,正则表达式引擎将继续匹配,直到遇到一个不被模式接收的字符。

3.Regex引擎非常贪婪只要模式匹配它将匹配尽可能多的字符。

4.Regex渴望实现匹配,所以将在需要时回溯以实现匹配。

5.Regex引擎总是先选择第一个选项。在|式表达式中。

以上的几点很重要。到这正则表达式的几乎所有规则也就讲完了。

最后附一个懒惰匹配常用修饰和其他的限定

*

尽可能少地使用重复的第一个匹配

+

尽可能少地使用重复但至少使用一次

??

使用零次重复(如有可能)或一次重复

{n}

等同于{n}

{n, }?

尽可能少地使用重复但至少使用n

{n,m}?

介于nm之间,尽可能少地使用重复


什么是RE? 
  想必各位大大在做文件查找的时侯都有使用过万用字符”*”,比如说想查找在Windows目录下所有的Word文件时,你可能就会用”*.doc”这样的方式来做查找,因为”*”所代表的是任意的字符。RE所做的就是类似这样的功能,但其功能更为强大。 

  写程序时,常需要比对字符串是否符合特定样式,RE最主要的功能就是来描述这特定的样式,因此可以将RE视为特定样式的描述式,举个例子来说,”\w+”所代表的就是任何字母与数字所组成的非空字符串(non-null string)。在.NET framework中提供了非常强大的类别库,藉此可以很轻易的使用RE来做文字的查找与取代、对复杂标头的译码及验证文字等工作。 
接下来,就让我们来体验一些例子吧。 

  一些简单的例子 
  假设要查找文章中Elvis后接有alive的文字符串的话,使用RE可能会经过下列的过程,括号是所下RE的意思: 

  1. elvis (查找elvis) 

  上述代表所要查找的字符顺序为elvis。在.NET中可以设定乎略字符的大小写,所以”Elvis”、”ELVIS”或者是”eLvIs”都是符合1所下的RE。但因为这只管字符出现的顺序为elvis,所以pelvis也是符合1所下的RE。可以用2的RE来改进。 

  2. \belvis\b (将elvis视为一整体的字查找,如elvis、Elvis乎略字符大小写时) 
“\b”在RE中有特别的意思,在上述的例子中所指的就是字的边界,所以\belvis\b用\b把elvis的前后边界界定出来,也就是要elvis这个字。 

  假设要将同一行里elvis后接有alive的文字符串找出来,此时就会用到另外二个特别意义的字符”.”及”*”。”.”所代表就是除了换行字符的任意字符,而”*”所代表的是重复*之前项目直到找到符合RE的字符串。所以”.*”所指的就是除了换行字符外的任意数目的字符数。所以查找同一行里elvis后接有alive的文字符串找出来,则可下如3之RE。 

  3. \belvis\b.*\balive\b (查找elvis后面接有alive的文字符串,如elvis is alive) 

  用简单之特别字符就可以组成功能强大的RE,但也发现当使用越来越多的特别字符时,RE就会越来越难看得懂了。 


再看看另外的例子 
  组成有效的电话号码 

  假使要从网页上收集顾客格式为xxx-xxxx的7位数字的电话号码,其中x是数字,RE可能会这样写。 

  4. \b\d\d\d-\d\d\d\d (查找七位数字之电话号码,如123-1234) 
  每一个\d代表一个数字。”-”则是一般的连字符号,为避免太多重复的\d,RE可以改写成如5的方式。 

  5. \b\d{3}-\d{4} (查找七位数字电话号码较好的方法,如123-1234) 
  在\d后的{3},代表重复前一个项目三次,也就是相等于\d\d\d。 

  RE的学习及测试工具 Expresso 

  因为RE不易阅读及使用者容易会下错RE的特性,Jim大大开发了一个工具软件Expresso,用来帮助使用者学习及测试RE,除了上面所述的网址之外,也可以上Ultrapico网站。安装完expresso后,在expression%20%20library中,jim大大把文章的例子都建立在其中,可以边看文章边测试,也可以试着修改范例所下的re,马上可以看到结果,小弟觉得非常好用。各位大大可以试试。/"。安装完Expresso后,在Expression Library中,Jim大大把文章的例子都建立在其中,可以边看文章边测试,也可以试着修改范例所下的RE,马上可以看到结果,小弟觉得非常好用。各位大大可以试试。 

  .NET中RE的基础概念 
  特殊字符 

  有些字符有特别的意义,比如之前所看到的”\b”、”.”、”*”、”\d”等。”\s”所代表的是任意空格符,比如说spaces、tabs、newlines等.。”\w”代表是任意字母或数字字符。 

  再看一些例子吧 
  6. \ba\w*\b (查找a开头的字,如able) 
  这RE描述要查找一个字的开始边界(\b),再来是字母”a”,再加任意数目的字母数字(\w*),再接结束这个字的结束边界(\b)。 

  7. \d+ (查找数字字符串) 
  “+”和”*”非常相似,除了+至少要重复前面的项目一次。也就是说至少有一个数字。 

  8. \b\w{6}\b (查找六个字母数字的字,如ab123c) 

  下表为RE常用的特殊字符 

  . 除了换行字符的任意字符 
  \w 任意字母数字字符 
  \s 任意空格符 
  \d 任意数字字符 
  \b 界定字的边界 
  ^ 文章的开头,如”^The'' 用以表示出现于文章开头的字符串为”The” 
  $ 文章的结尾,如”End$”用以表示出现在文章的结尾为”End” 
  特殊字符”^”及”$”是用来查找某些字必需是文章的开头或结尾,这在验证输入是否符合某一样式时特别用有,比如说要验证七位数字的电话号码,可能会输入如下9的RE。 

  9. ^\d{3}-\d{4}$ (验证七位数字之电话号码) 

  这和第5个RE相同,但其前后都无其它的字符,也就是整串字符串只有这七个数字的电话号码。在.NET中如果设定Multiline这个选项,则”^”和”$”会每行进行比较,只要某行的开头结尾符合RE即可,而不是整个文章字符串做一次比较。 

  转意字符(Escaped characters) 

  有时可能会需要”^”、”$”单纯的字面意义(literal meaning)而不要将它们当成特殊字符,此时”\”字符就是用来移除特殊字符特别意义的字符,因此”\^”、”\.”、”\\”所代表的就是”^”、”.”、”\”的字面意义。 

  重复前述项目 

  在前面看过”{3}”及”*”可以用来重复前述字符,之后我们会看到如何用同样的语法重复整个次描述(subexpressions)。下表是使用重复前述项目的一些方式。 

  * 重复任意次数 
  + 重复至少一次 
  ? 重复零次或一次 
  {n} 重复n次 
  {n,m} 重复至少n次,但不超过m次 
  {n,} 重复至少n次 

  再来试一些例子吧 

  10. \b\w{5,6}\b (查找五个或六个字母数字字符的字,如as25d、d58sdf等) 
  11. \b\d{3}\s\d{3}-\d{4} (查找十个数字的电话号码,如800 123-1234) 
  12. \d{3}-\d{2}-\d{4} (查找社会保险号码,如 123-45-6789) 
  13. ^\w* (每行或整篇文章的第一个字) 
  在Espresso可试试有Multiline和没Multiline的不同。 

  匹配某范围的字符 

  有时需要查找某些特定的字符时怎么辨?这时中括号”[]”就派上了用场。因此[aeiou]所要查找的是”a”、”e”、”i”、”o”、”u”这些元音,[.?!]所要查找的是”.”、”?”、”!”这些符号,在中括号中的特殊字符的特别意义都会被移除,也就是解译成单纯的字面意义。也可以指定某些范围的字符,如”[a-z0-9]”,所指的就是任意小写字母或任意数字。 

  接下来再看一个比较初复杂查找电话号码的RE例子 

  14. \(?\d{3}[( ] \s?\d{3}[- ]\d{4} (查找十位数字之电话号码,如(080) 333-1234 ) 

  这样的RE可查找出较多种格式的电话号码,如(080) 123-4567、511 254 6654等。”\(?”代表一个或零个左小括号”(“,而”[( ]”代表查找一个右小括号”)”或空格符,”\s?”指一个或零个空格符组。但这样的RE会将类似”800) 45-3321”这样的电话找出来,也就是括号没有对称平衡的问题,之后会学到择一(alternatives)来决解这样的问题。 

  不包含在某特定字符组里(Negation) 

  有时需要查找在包含在某特定字符组里的字符,下表说明如何做类似这样的描述。 

  \W 不是字母数字的任意字符 
  \S 不是空格符的任意字符 
  \D 不是数字字符的任意字符 
  \B 不在字边界的位置 
  [^x] 不是x的任意字符 
  [^aeiou] 不是a、e、i、o、u的任意字符 

  15. \S+ (不包含空格符的字符串) 

  择一(Alternatives) 

  有时会需要查找几个特定的选择,此时”|”这个特殊字符就派上用场了,举例来说,要查找五个数字及九个数字(有”-”号)的邮政编码。 

  16. \b\d{5}-\d{4}\b|\b\d{5}\b (查找五个数字及九个数字(有”-”号)的邮政编码) 

  在使用Alternatives时需要注意的是前后的次序,因为RE在Alternatives中会优先选择符合最左边的项目,16中,如果把查找五个数字的项目放在前面,则这RE只会找到五个数字的邮政编码。了解了择一,可将14做更好的修正。 

  17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} (十个数字的电话号码) 

  群组(Grouping) 

  括号可以用来介定一个次描述,经由次描述的介定,可以针对次描述做重复或及他的处理。 

  18. (\d{1,3}\.){3}\d{1,3} (寻找网络地址的简单RE) 

  此RE的意思第一个部分(\d{1,3}\.){3},所指的是,数字最小一位最多三位,并且后面接有”.”符号,此类型的共有三个,之后再接一到三位的数字,也就是如192.72.28.1这样的数字。 

  但这样会有个缺点,因为网络地址数字最多只到255,但上述的RE只要是一到三位的数字都是符合的,所以这需要让比较的数字小于256才行,但只单独使用RE并无法做这样的比较。在19中使用择一来将地址的限制在所需要的范围内,也就是0到255。 

  19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) (寻找网络地址) 

  有没有发觉RE越来越像外星人说的话了?就以简单的寻找网络地址,直接看RE都满难理解的哩。 

  Expresso Analyzer View 

  Expresso提供了一个功能,它可以将所下的RE变成树状的说明,一组组的分开说明,提供了一个好的除错环境。其它的功能,如部分符合(Partial Match只查找反白RE的部分)及除外符合(Exclude Match只不查找反白RE的部分)就留给各位大大试试啰。 

  当次描述用括号群组起来时,符合次描述的文字可用在之后的程序处理或RE本身。在预设的情型下,所符合的群组是由数字命名,由1开始,由顺序是由左至右,这自动群组命名,可在Expresso中的skeleton view或result view中看到。 

  Backreference是用来查找群组中抓取的符合文字所相同的文字。举例来说”\1”所指符合群组1所抓取的文字。 

  20. \b(\w+)\b\s*\1\b (寻找重复字,此处说的重复是指同样的字,中间有空白隔开如dog dog这样的字) 
(\w+)会抓取至少一个字符的字母或数字的字,并将它命名为群组1,之后是查找任意空格符,再接和群组1相同的文字。 

  如果不喜欢群组自动命名的1,也可以自行命名,以上述例子为例,(\w+)改写为(?<Word>\w+),这就是将所抓取的群组命名为Word,Backreference就要改写成为\k<Word> 
21. \b(?<Word>\w+)\b\s*\k<Word>\b (使用自行命名群组抓取重复字) 

  使用括号还有许多特别的语法元素,比较通用的列表如下: 

  抓取(Captures) 
  (exp) 符合exp并抓取它进自动命名的群组 
  (?<name>exp) 符合exp并抓取它进命名的群组name 
  (?:exp) 符合exp,不抓取它 
  Lookarounds 
  (?=exp) 符合字尾为exp的文字 
  (?<=exp) 符合前缀为exp的文字 
  (?!exp) 符合后面没接exp字尾的文字 
  (?<!exp) 符合前面没接exp前缀的文字 
  批注Comment 
  (?#comment) 批注 

  Positive Lookaround 

  接下来要谈的是lookahead及lookbehind assertions。它们所查找的是目前符合之前或之后的文字,并不包含目前符合本身。这些就如同”^”及”\b”特殊字符,本身并不会对应任何文字(用来界定位置),也因此称做是zero-width assertions,看些例子也许会清楚些。 

  (?=exp)是一个”zero-width positive lookahead assertion”。它指的就是符合字尾为exp的文字,但不包含exp本身。 

  22. \b\w+(?=ing\b) (字尾为ing的字,比如说filling所符合的就是fill) 
(?<=exp)是一个”zero-width positive lookbehind assertion”。它指的就是符合前缀为exp的文字,但不包含exp本身。 

  23. (?<=\bre)\w+\b (前缀为re的字,比如说repeated所符合的就是peated) 
  24. (?<=\d)\d{3}\b (在字尾的三位数字,且之前接一位数字) 
  25. (?<=\s)\w+(?=\s) (由空格符分隔开的字母数字字符串) 

  Negative Lookaround 

  之前有提到,如何查找一个非特定或非在特定群组的字符。但如果只是要验证某字符不存在而不要对应这些字符进来呢?举个例子来说,假设要查找一个字,它的字母里有q但接下来的字母不是u,可以用下列的RE来做。 

  26. \b\w*q[^u]\w*\b (一个字,其字母里有q但接下来的字母不是u) 

  这样的RE会有一个问题,因为[^u]要对应一个字符,所以若q是字的最后一个字母,[^u]这样的下法就会将空格符对应下去,结果就有可能会符合二个字,比如说”Iraq haha”这样的文字。使用Negative Lookaround就能解决这样的问题。 

  27. \b\w*q(?!u)\w*\b (一个字,其字母里有q但接下来的字母不是u) 
  这是”zero-width negative lookahead assertion”。 

  28. \d{3}(?!\d) (三个位的数字,其后不接一个位数字) 

  同样的,可以使用(?<!exp),”zero-width negative lookbehind assertion”,来符合前面没接exp前缀的文字符串。 

  29. (?<![a-z ])\w{7} (七个字母数字的字符串,其前面没接字母或空格) 

30. (?<=<(\w+)>.*(?=<\/\1> (HTML卷标间的文字) 
  这使用lookahead及lookbehind assertion来取出HTML间的文字,不包括HTML卷标。 

  请批注(Comments Please) 
  括号还有个特殊的用途就是用来包住批注,语法为”(?#comment)”,若设定”Ignore Pattern Whitespace”选项,则RE中的空格符当RE使用时会乎略。此选项设定时,”#”之后的文字会乎略。 

  31. HTML卷标间的文字,加上批注 

  (?<=  #查找前缀,但不包含它 
  <(\w+)> #HTML标签 
  ) #结束查找前缀 
  .* #符合任何文字 
  (?= #查找字尾,但不包含它 
  <\/\1> #符合所抓取群组1之字符串,也就是前面小括号的HTML标签 
  ) #结束查找字尾 

  寻找最多字符的字及最少字符的字(Greedy and Lazy) 
  当RE下要查找一个范围的重复时(如”.*”),它通常会寻找最多字符的符合字,也就是Greedy matching。举例来说。 

  32. a.*b (开始为a结束为b的最多字符的符合字) 

  若有一字符串是”aabab”,使用上述RE所得到的符合字符串就是”aabab”,因为这是寻找最多字符的字。有时希望是符合最少字符的字也就是lazy matching。只要将重复前述项目的表加上问号(?)就可以把它们全部变成lazy matching。因此”*?”代表的就是重复任意次数,但是使用最少重复的次数来符合。举个例子来说: 

  33. a.*?b (开始为a结束为b的最少字符的符合字) 

  若有一字符串是”aabab”,使用上述RE第一个所得到的符合字符串就是”aab”再来是”ab”,因为这是寻找最少字符的字。 

  *? 重复任意次数,最少重复次数为原则 
  +? 重复至少一次,最少重复次数为原则 
  ?? 重复零次或一次,最少重复次数为原则 
  {n,m}? 重复至少n次,但不超过m次,最少重复次数为原则 
  {n,}? 重复至少n次,最少重复次数为原则 

还有什么没提到呢? 

  到目前为止,已经提到了许多建立RE的元素,当然还有许多元素没有提到,下表整理了一些没提到的元素,在最左边的字段的数字是说明在Expresso中的例子。 

  # 语法 说明 

  \a Bell 字符 
  \b 通常是指字的边界,在字符组里所代表的就是backspace 
  \t Tab 

  34 \r Carriage return 

  \v Vertical Tab 
  \f From feed 

  35 \n New line 
  \e Escape 

  36 \nnn ASCII八位码为nnn的字符 

  37 \xnn 十六位码为nn的字符 

  38 \unnnn Unicode为nnnn的字符 

  39 \cN Control N字符,举例来说Ctrl-M是\cM 

  40 \A 字符串的开始(和^相似,但不需籍由multiline选项) 

  41 \Z 字符串的结尾 
  \z 字符串的结尾 

  42 \G 目前查找的开始 

  43 \p{name} Unicode 字符组名称为name的字符,比如说\p{Lowercase_Letter} 所指的就是小写字 
  (?>exp) Greedy次描述,又称之为non-backtracking次描述。这只符合一次且不采backtracking。 

  44 (?<x>-<y>exp) 

  or (?-<y>exp) 平衡群组。虽复杂但好用。它让已命名的抓取群组可以在堆栈中操作使用。(小弟对这个也是不太懂哩) 

  45 (?im-nsx:exp) 为次描述exp更改RE选项,比如(?-i:Elvis)就是把Elvis大乎略大小写的选项关掉 

  46 (?im-nsx) 为之后的群组更改RE选项。 
  (?(exp)yes|no) 次描述exp视为zero-width positive lookahead。若此时有符合,则yes次描述为下一个符合标的,若否,则no 次描述为下一个符合标的。 
  (?(exp)yes) 和上述相同但无no次描述 
  (?(name)yes|no) 若name群组为有效群组名称,则yes次描述为下一个符合标的,若否,则no 次描述为下一个符合标的。 

  47 (?(name)yes) 和上述相同但无no次描述 




匹配中文字符的正则表达式:

[ \ 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地址
下面是利用正则表达式匹配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! " )
}
}

不过上面的程序如果不用正则表达式,而直接用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

*注
===============================
如果var s = “abacabefggeeii”
结果就不对了,结果为:abeicfgg
正则表达式的能力有限
===============================

我原来在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,'') "   onbeforepaste = " clipboardData.setData('text',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,'')  " onbeforepaste = " clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/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 *\ / \1\s*>

Visual Basic & C# Regular Expression
1.确认有效电子邮件格式
下面的示例使用静态 Regex.IsMatch 方法验证一个字符串是否为有效电子邮件格式。如果字符串包含一个有效的电子邮件地址,则 IsValidEmail 方法返回 true,否则返回 false,但不采取其他任何操作。您可以使用 IsValidEmail,在应用程序将地址存储在数据库中或显示在 ASP.NET 页中之前,筛选出包含无效字符的电子邮件地址。

[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 }\.[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 }\.[0-9]{ 1,3 }\.[0-9]{ 1,3 }\.)|(([\w-]+\.)+))([a-zA-Z]{ 2,4 }|[0-9]{ 1,3 })(\]?)$");
}

2.清理输入字符串
下面的代码示例使用静态 Regex.Replace 方法从字符串中抽出无效字符。您可以使用这里定义的 CleanInput 方法,清除掉在接受用户输入的窗体的文本字段中输入的可能有害的字符。CleanInput 在清除掉除 @、-(连字符)和 .(句点)以外的所有非字母数字字符后返回一个字符串。

[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.更改日期格式
以下代码示例使用 Regex.Replace 方法来用 dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式。

[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 的替换模式中使用命名的反向引用。其中,替换表达式 ${ day } 插入由 (?…) 组捕获的子字符串。

有几种静态函数使您可以在使用正则表达式操作时无需创建显式正则表达式对象,而 Regex.Replace 函数正是其中之一。如果您不想保留编译的正则表达式,这将给您带来方便

4.提取 URL 信息
以下代码示例使用 Match.Result 来从 URL 提取协议和端口号。例如,“http://www.penner.cn:8080……将返回“http:8080”。

[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位,且数字字母都包含的密码的正则表达式
在C#中,可以用这个来表示:

" \w{ 6 }(\w+)* "

一个将需要将路径字符串拆分为根目录和子目录两部分的算法程序,考虑路径格式有:C:\aa\bb\cc ,\\aa\bb\cc , ftp://aa.bb/cc 上述路径将分别被拆分为:C:\和aa\bb\cc ,\\aa 和 \bb\cc , ftp:// 和 aa.bb/cc 用javascript实现如下:

var   strRoot , strSub
var   regPathParse = / ^([^\\^ \/ ]+[\\ \/ ]+|\\\\[^\\]+)(.*)$ /
if ( regPathParse . test ( strFolder ))
{
strRoot = RegExp .$ 1
strSub = RegExp .$ 2
}


ps:
一个教程的链接:http://blog.csdn.net/wushuai1346/article/details/7206647
http://blog.csdn.net/wushuai1346/article/details/7180920
对于需求为:匹配以A为起始,B为结尾的字符串的情形,中间的内容不关心,且需要是极小字符串的。
正则表达式如下:A(.*?)B,其中.*表示任意字符,?表示极小字符串的需求。

如果需求是极大项的贪婪选择该如何写正则表达式?

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)ab(第四到第五个字符)

为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权——The match that begins earliest wins。

表5.懒惰限定符
代码/语法说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复



ps:获取正则表达式查询结果集中的内容。正则查询结果是一个List对象,使用for i in list:就可以得到其中的数据项,i。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值