(转贴)正则表达式之道

表达式之道

原著:Steve Mansour
sman@scruznet.com
Revised: June 5, 1999
(copied by jm /at/ jmason.org from http://www.scruz.net/%7esman/regexp.htm, after the original disappeared! )

Neo Lee
neo.lee@gmail.com
20041016

英文版原文

者按:原文因年代久,文中很多接早已期(主要是vised等工具的介和手册),本文中已将此类链除,如需检查这接可以看上面接的原文。除此之外基本照原文直,括号中有“者按”的部分是充的明。如有内容方面的问题请直接和Steve Mansor系,当然,如果你只写中文,也可以和我系。

是正表达式
范例
  
简单
  
(神奇的咒
  
(不可思的象形文字)
不同工具中的正表达式

是正表达式

一个正表达式,就是用某模式去匹配一字符串的一个公式。很多人因看上去比古怪而且复杂所以不敢去使用——很不幸,篇文章也不能变这一点,不经过一点点练习之后我就复杂的表达式其写起来是相当简单的,而且,一旦你弄懂它,你就能把数小辛苦而且易的文本理工作压缩在几分(甚至几秒)内完成。正表达式被各文本编辑软件、类库(例如Rogue Wavetools.h++)、脚本工具(像awk/grep/sed)广泛的支持,而且像MicrosoftVisual C++这种交互式IDE始支持它了。

将在如下的章中利用一些例子来解表达式的用法,大部分的例子是基于vi中的文本替命令和grep文件搜索命令来写的,不都是比典型的例子,其中的概念可以在sedawkperl和其他支持正表达式的言中使用。你可以看看不同工具中的正表达式,其中有一些在的工具中使用正表达式的例子。有一个vi中文本替命令(s)的简单说附在文后供参考。

表达式基

表达式由一些普通字符和一些元字符(metacharacters成。普通字符包括大小写的字母和数字,而元字符具有特殊的含,我下面会予解

在最简单的情况下,一个正表达式看上去就是一个普通的找串。例如,正表达式"testing"中没有包含任何元字符,,它可以匹配"testing""123testing"等字符串,但是不能匹配"Testing"

要想真正的用好正表达式,正确的理解元字符是最重要的事情。下表列出了所有的元字符和的一个短的描述。

元字符

 

描述


.


匹配任何个字符。例如正表达式r.t匹配些字符串:ratrutr t,但是不匹配root。 

$


匹配行束符。例如正表达式weasel$ 匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels."。 

^


匹配一行的始。例如正表达式^When in匹配字符串"When in the course of human events"始,但是不能匹配"What and When in the"

*


匹配0或多个正好在它之前的那个字符。例如正表达式.*意味着能匹配任意数量的任何字符。

\


是引用府,用来将里列出的些元字符当作普通的字符来行匹配。例如正表达式\$被用来匹配美元符号,而不是行尾,似的,正表达式\.用来匹配点字符,而不是任何字符的通配符。

[ ] 
[c1-c2]
[^c1-c2]


匹配括号中的任何一个字符。例如正表达式r[aou]t匹配ratrotrut,但是不匹配ret。可以在括号中使用字符-来指定字符的区,例如正表达式[0-9]可以匹配任何数字字符;可以制定多个区,例如正表达式[A-Za-z]可以匹配任何大小写字母。另一个重要的用法是“排除”,要想匹配除了指定区之外的字符——也就是所集——在左的括号和第一个字符之使用^字符,例如正表达式[^269A-Z] 将匹配除了269和所有大写字母之外的任何字符。

\< \>


匹配word)的始(\<)和束(\>)。例如正表达式\<the匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"注意个元字符不是所有的件都支持的。

\( \)


\( \) 的表达式定义为”(group),并且将匹配个表达式的字符保存到一个临时区域(一个正表达式中最多可以保存9个),它可以用 \1 \9 的符号来引用。

|


将两个匹配条件逻辑“或”(Or)运算。例如正表达式(him|her) 匹配"it belongs to him""it belongs to her",但是不能匹配"it belongs to them."注意个元字符不是所有的件都支持的。

+


匹配1或多个正好在它之前的那个字符。例如正表达式9+匹配999999等。注意个元字符不是所有的件都支持的。

?


匹配01个正好在它之前的那个字符。注意个元字符不是所有的件都支持的。

\{i\}
\{
i,j\}


匹配指定数目的字符,些字符是在它之前的表达式定的。例如正表达式A[0-9]\{3\} 匹配字符"A"后面跟着正好3个数字字符的串,例如A123A348等,但是不匹配A1234。而正表达式[0-9]\{4,6\} 匹配连续的任意4个、5个或者6个数字字符。注意个元字符不是所有的件都支持的。

简单的元字符是点,它能匹配任何个字符(注意包括新行符)。假定有个文件test.txt包含以下几行内容:

he is a rat
he is in a rut
the food is Rotten
I like root beer

可以使用grep命令来测试的正表达式,grep命令使用正表达式去尝试匹配指定文件的一行,并将至少有一匹配表达式的所有行示出来。命令

grep r.t test.txt

test.txt文件中的一行中搜索正表达式r.t,并打印出匹配的行。正表达式r.t匹配一个r接着任何一个字符再接着一个t。所以它将匹配文件中的ratrut,而不能匹配Rotten中的Rot,因表达式是大小写敏感的。要想同匹配大写和小写字母,应该使用字符区元字符(方括号)。正表达式[Rr]匹配Rr。所以,要想匹配一个大写或者小写的r接着任何一个字符再接着一个t就要使用个表达式:[Rr].t

要想匹配行首的字符要使用抑字符(^)——又是也被叫做插入符。例如,想找到text.txt中行首"he"的行,你可能会先用简单表达式he,但是会匹配第三行的the,所以要使用正表达式^he,它只匹配在行首出h

候指定“除了×××都匹配”会比容易达到目的,当抑字符(^)出在方括号中是,它表示“排除”,例如要匹配he ,但是排除前面是t or s的情性(也就是theshe),可以使用:[^st]he

可以使用方括号来指定多个字符区。例如正表达式[A-Za-z]匹配任何字母,包括大写和小写的;正表达式[A-Za-z][A-Za-z]* 匹配一个字母后面接着0或者多个字母(大写或者小写)。当然我也可以用元字符+做到同的事情,也就是:[A-Za-z]+ ,和[A-Za-z][A-Za-z]*完全等价。但是要注意元字符+ 并不是所有支持正表达式的程序都支持的。一点可以参考后面的表达式法支持情况

要指定特定数量的匹配,要使用大括号(注意必使用反斜杠来转义)。想匹配所有1001000例而排除1010000,可以使用:10\{2,3\}个正表达式匹配数字1后面跟着2或者30的模式。在个元字符的使用中一个有用的化是忽略第二个数字,例如正表达式0\{3,\} 将匹配至少3连续0

简单的例子

里有一些有代表性的、比较简单的例子。

vi 命令

作用

:%s/ */ /g

把一个或者多个空格替换为一个空格。

:%s/ *$//

去掉行尾的所有空格。

:%s/^/ /

一行上加入一个空格。

:%s/^[0-9][0-9]* //

去掉行首的所有数字字符。

:%s/b[aeio]g/bug/g

将所有的bagbegbigbogbug。 

:%s/t\([aou]\)g/h\1t/g

将所有tagtogtughathothug(注意用group的用法和使用\1引用前面被匹配的字符)。



的例子(神奇的咒

1

将所有方法foo(a,b,c)例改foo(b,a,c)abc可以是任何提供方法foo()的参数。也就是实现这样转换

之前

 

之后

foo(10,7,2)


foo(7,10,2)

foo(x+13,y-2,10)


foo(y-2,x+13,10)

foo( bar(8), x+y+z, 5)


foo( x+y+z, bar(8), 5)

下面条替命令能够实现这一魔法:

:%s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g

把它打散来加以分析。写出个表达式的基本思路是找出foo()和它的括号中的三个参数的位置。第一个参数是用个表达式来识别的::\([^,]*\),我可以从里向外来分析它: 

[^,]

 

除了逗号之外的任何字符

[^,]*


0或者多个非逗号字符

\([^,]*\)


些非逗号字符标记为\1这样可以在之后的替模式表达式中引用它

\([^,]*\),


找到0或者多个非逗号字符后面跟着一个逗号,并且非逗号字符那部分要标记出来以后用。

在正是指出一个使用正表达式常见错误的最佳机。要使用[^,]*这样的一个表达式,而不是更加简单直接的写法,例如:.*,来匹配第一个参数呢?想我使用模式.*来匹配字符串"10,7,2",它应该匹配"10,""10,7,"了解决个两性(ambiguity),正表达式定一律按照最的串来,在上面的例子中就是"10,7,"这样就找出了两个参数而不是我期望的一个。所以,我要使用[^,]*制取出第一个逗号之前的部分。

个表达式我分析到了:foo(\([^,]*\)一段可以简单的翻译为“当你找到foo(就把其后直到第一个逗号之前的部分标记为\1。然后我使用同标记第二个参数\2第三个参数的标记方法也是一,只是我要搜索所有的字符直到右括号。我并没有必要去搜索第三个参数,因不需要整它的位置,但是这样的模式能只去替那些有三个参数的foo()方法用,在foo()是一个重overoading)方法时这种明确的模式往往是比的。然后,在替部分,我找到foo()对应实例,然后利用标记好的部分行替,是的第一和第二个参数交位置。

2

有一个CSVcomma separated value)文件,里面有一些我需要的信息,但是格式却有问题,目前数据的列序是:姓名,公司名,州名写,编码在我希望讲这些数据重新组织,以便在我的某个件中使用,需要的格式:姓名,州名-编码,公司名。也就是,我整列序,要合并两个列来构成一个新列。另外,我件不能接受逗号前后面有任何空格(包括空格和制表符)所以我们还要去掉逗号前后的所有空格。

里有几行我们现在的数据:

Bill Jones,     HI-TEK Corporation ,  CA, 95011
Sharon Lee Smith,  Design Works Incorporated,  CA, 95012
B. Amos   ,  Hill Street Cafe,  CA, 95013
Alexander Weatherworth,  The Crafts Store,  CA, 95014
...

希望把它子:

Bill Jones,CA 95011,HI-TEK Corporation
Sharon Lee Smith,CA 95012,Design Works Incorporated
B. Amos,CA 95013,Hill Street Cafe
Alexander Weatherworth,CA 95014,The Crafts Store
...

将用两个正表达式来解决问题。第一个移列和合并列,第二个用来去掉空格。

下面就是第一个替命令:

:%s/\([^,]*\),\([^,]*\),\([^,]*\),\(.*\)/\1,\3 \4,\2/

里的方法跟例1基本一,第一个列(姓名)用个表达式来匹配:\([^,]*\),即第一个逗号之前的所有字符,而姓名内容被用\1标记下来。公司名和州名写字段用同的方法标记为\2\3,而最后一个字段用\(.*\)来匹配("匹配所有字符直到行末")。替部分引用上面标记的那些内容来行构造。

下面个替命令用来去除空格:

:%s/[ \t]*,[ \t]*/,/g

们还是分解来看:[ \t]匹配空格/制表符,[ \t]* 匹配0或多个空格/制表符,[ \t]*,匹配0或多个空格/制表符后面再加一个逗号,最后,[ \t]*,[ \t]*匹配0或多个空格/制表符接着一个逗号再接着0或多个空格/制表符。在替部分,我们简单的我找到的所有西替成一个逗号。里我使用了尾的可g参数,表示在行中所有匹配的串行替(而不是缺省的只替第一个匹配串)。

3

有一个多字符的片断重,例如:

Billy tried really hard
Sally tried really really hard
Timmy tried really really really hard
Johnny tried really really really really hard

而你想把"really""really really",以及任意数量连续"really"字符串成一个简单"very"simple is good!),那以下命令:

:%s/\(really \)\(really \)*/very /

就会把上述的文本成:

Billy tried very hard
Sally tried very hard
Timmy tried very hard
Johnny tried very hard

表达式\(really \)*匹配0或多个连续"really "(注意尾有个空格),而\(really \)\(really \)* 匹配1个或多个连续"really "例。

的例子(不可思的象形文字)

Coming soon.

不同工具中的正表达式

OK,你已使用REregular expressions,正表达式),但是你并准使用vi。所以,在里我们给出一些在其他工具中使用RE的例子。另外,我总结一下你在不同程序之使用RE可能发现的区

当然,你也可以在Visual C++编辑器中使用RE选择Edit->Replace,然后选择"Regular expression"选择框,Find What入框对应上面介vi命令:%s/pat1/pat2/g中的pat1部分,而Replace入框对应pat2部分。但是,了得到vi行范g选项,你要使用Replace All或者适当的手工Find Next and Replace者按:知道为啥有人弱智了吧,VC中可以中一个范的文本,然后在其中行替,但是之不vi灵活和典雅)。

sed

SedStream EDitor写,是Unix下常用的基于文件和管道的编辑工具,可以在手册中得到sed详细信息。

里是一些有趣的sed脚本,假定我正在理一个叫做price.txt的文件。注意编辑并不会改源文件,sed只是理源文件的一行并把示在出中(当然很容易使用重定向来定制):

sed脚本

 

描述


sed 's/^$/d' price.txt


除所有空行

sed 's/^[ \t]*$/d' price.txt


除所有只包含空格或者制表符的行

sed 's/"//g' price.txt


除所有引号

awk

awk是一种编言,可以用来文本数据复杂的分析和理。可以在手册中得到awk详细信息。个古怪的名字是它作者的姓的写(AhoWeinbergerKernighan)。

AhoWeinbergerKernighanThe AWK Programming Language中有很多很好的awk的例子,不要下面些微不足道的脚本例子限制你awk大能力的理解。我假定我们针对price.txt文件理,跟sedawk也只是把示在端上。 

awk脚本

 

描述


awk '$0 !~ /^$/' price.txt


除所有空行

awk 'NF > 0' price.txt


awk中一个更好的除所有行的

awk '$2 ~ /^[JT]/ {print $3}' price.txt


打印所有第二个字段是'J'或者'T'的行中的第三个字段

awk '$2 !~ /[Mm]isc/ {print $3 + $4}' price.txt


针对所有第二个字段不包含'Misc'或者'misc'的行,打印第3和第4列的和(假定数字)

awk '$3 !~ /^[0-9]+\.[0-9]*$/ {print $0}' price.txt


打印所有第三个字段不是数字的行,里数字是指d.d或者d这样的形式,其中d09的任何数字

awk '$2 ~ /John|Fred/ {print $0}' price.txt


如果第二个字段包含'John'或者'Fred'打印整行

grep

grep是一个用来在一个或者多个文件或者入流中使用RE找的程序。它的name言可以用来针对文件和管道理。可以在手册中得到grep的完整信息。个同古怪的名字来源于vi的一个命令,g/re/p,意思是global regular expression print

下面的例子中我假定在文件phone.txt中包含以下的文本,——其格式是姓加一个逗号,然后是名,然后是一个制表符,然后是电话

Francis, John           5-3871
Wong, Fred              4-4123
Jones, Thomas           1-4122
Salazar, Richard        5-2522

grep命令

 

描述


grep '\t5-...1' phone.txt


把所有电话5开头1束的行打印出来,注意制表符是用\t表示的

grep '^S[^ ]* R' phone.txt


打印所有姓以S和名以R的行

grep '^[JW]' phone.txt


打印所有姓开头J或者W的行

grep ', ....\t' phone.txt


打印所有姓是4个字符的行,注意制表符是用\t表示的

grep -v '^[JW]' phone.txt


打印所有不以J或者W开头的行

grep '^[M-Z]' phone.txt


打印所有姓的开头MZ任一字符的行

grep '^[M-Z].*[12]' phone.txt


打印所有姓的开头MZ任一字符,并且点号号码结尾是1或者2的行

egrep

egrepgrep的一个展版本,它在它的正表达式中支持更多的元字符。下面的例子中我假定在文件phone.txt中包含以下的文本,——其格式是姓加一个逗号,然后是名,然后是一个制表符,然后是电话

Francis, John           5-3871
Wong, Fred              4-4123
Jones, Thomas           1-4122
Salazar, Richard        5-2522

egrep command

 

Description


egrep '(John|Fred)' phone.txt


打印所有包含名字John或者Fred的行

egrep 'John|22$|^W' phone.txt


打印所有包含John 或者以22束或者以W的行

egrep 'net(work)?s' report.txt


report.txt中找到所有包含networks或者nets的行

表达式法支持情况

命令或

.

[ ]

^

$

\( \)

\{ \}

?

+

|

( )

vi

 

 

 

 

 

 

 

 

 

 

Visual C++

 

 

 

 

 

 

 

 

 

 

awk

 

 

 

 

 

 

 

 

 

 

sed

 

 

 

 

 

 

 

 

 

 

Tcl

 

 

 

 

 

 

 

 

 

 

ex

 

 

 

 

 

 

 

 

 

 

grep

 

 

 

 

 

 

 

 

 

 

egrep

 

 X

 

 

 

 

 

 

 

 

fgrep

 

 

 

 

 

 

 

 

 

 

perl

 X

 X

 X

 X

 X

 

 X

 X

 X

 X

 

vi命令

Vi的替命令:

:ranges/pat1/pat2/g

其中

: Vi的命令行界面。

range 是命令行范的指定,可以使用百分号(%)表示所有行,使用点(.)表示当前行,使用美元符号($)表示最后一行。你可以使用行号,例如10,20表示第1020行,.,$表示当前行到最后一行,.+2,$-5表示当前行后两行直到全文的倒数第五行,等等。

s 表示其后是一个替命令。

pat1 是要找的一个正表达式,篇文章中有一大堆例子。

pat2 是希望把匹配串成的模式的正表达式,篇文章中有一大堆例子。

g 选标志,带这志表示替针对行中个匹配的串行,否则则只替行中第一个匹配串。

网上有很多vi的在线手册,你可以访问得更加完整的信息。

[回到主]


C#中的正表达式



Jeffrey E.F. Friedl
写了一本于正表达式的《精通正表达式》。作者了使者更好的理解和掌握正表达式,造了一个故事。该书言以perl主。据我所知C#中的正表达式也是基于perl5。所以它们应该多的共同之

,我并不打算原封不对该书的内容行翻,一则这内容太多了,我根本就不任翻译这项工作;二如果我真的把译过来,同把里面的代码换C#,在没有征得原作者的情况下,可能有侵的嫌疑了。所以,当作读书好了。



的前言,我可以直接入第一章:



表达式



作者说这一章是表达式的绝对而准的,目的是以后的章打下坚实的基。那如果你是不是菜,你可以忽略一章。



故事景:

你的档案部的儿想要一个工具用来检查单词(如:this this),一个在大量编辑文档的候通常会遇到的问题。你的工作就是建一个解决方案:

接受任何数量要检查的文件,个文件中有重复单词的那些行,突出些重单词,同确保原文件名称和些行出表中。

跨行检查,找到一行的最后一个单词和下一行开头第一个单词的情况。

找出重单词,不管他是否大小写不同(如:The the),以及允些重复单词含有不同数量的空白字符(空格、制表符、新行等)

找出重单词,甚至单词Html标签(如:…it is <B>very</B> very important.)



要解决上述的实际问题,我首先要做的就是写出正表达式,找到我想要的文本,忽略我不需要的文本,然后使用我C#码对获取的文本理。



在使用正表达式之前,你也多少已知道什是正表达式。甚至你不知道,你几乎可以肯定已熟悉它的基本概念了。

你知道report.txt是一个具体的文件名称,但是如果你有任何Unix或者DOS/Windows经验,你也知道“*.txt”可以用来选择多个文件。这种形式的文件名,有一些字符有着特殊的含。星号意味着匹配任何西,号意味着匹配一个字符。如:“*.txt”表示任何文件名以.txt尾的文件。

文件名称得模式匹配,使用了有限的匹配符。有当前网上的搜索引擎也允使用某些指定的匹配符来行内容搜索。正表达式采用丰富的匹配字符,可以理各种复杂问题



首先我两个位置匹配符:

^ :
表示一行文字的始位置

: 表示一行文字的束位置



如:表达式:"^Cat", 匹配的单词Cat在行的,注意^是一个位置字符,不是要匹配字符的本身。

,表达式:"Cat$" 匹配的单词Cat来一行的



接下来,我表达式中的方括号"[]", 它表示匹配括号中字符中的一个。如:

表达式:"[0123456789]"将匹配数字09的任何一个。

例如:我找文本中,所有包含gray或者grey,那表达式可以这么写:"gr[ea]y"

[ea]
表示匹配ea中的一个,而不是整个ea



如果我要匹配html中的<H1><H2><H3><H4><H5><H6>标签,我可以写表达式:

"<H[123456]>"
,但是如果我要匹配所有字符中的一个呢?哈,问题就来了,在方括号中写出所有的字符?很幸运,我不必这么做,我符号"-";

使用范符号,我只需要出一个范界字符即可,上面的Html例子,我可以写成:"<H[1-6]>"

而表达式:"[0-9a-zA-Z]"的意思在清楚了吧?它匹配数字字符,小写26个字母和大写26个字母中的一个。



[]中的"^"符号

如果你看到表达式如:"[^0-9]","^"不再是前面的位置符号,里它是否定符号,表示排除的意思,上面的表达式,表示不包含数字09的字符。



思考1:表达式"q[^u]"的意思。假如有下列的单词,那些将被匹配?

Iraqi

Iraqian

miqra

qasida

qintar

qoph

zaqqum





除了范字符的表示之外,有一个是点字符".",点字符出在表达式中,表示匹配任何字符。

如表达式:"07.04.76"将匹配:

形如:07/04/76, 07-04-7607.04.76



如果我需要在某些字符中可选择,我可以采用选项字符"|"

选项字符有“或"的意思,比如表达式:"[Bob|Robert]"表示Bob或者Robert将被匹配。

在看我前面提到的表达式:"gr[ea]y" ,利用选项字符我可以写作"grey|gray",是相同的。

括号的使用:括号在表达式中也是被作元字符使用,如前面的表达式,我可以写成:"gr(e|a)y"里的括号是必的,如果没有括号,那表达式"gre|ay"将匹配gre或者ay不是我想要的果。如果你不是很清楚,看一下下面的例子:

件中找所有以From:或者Subject:或者Date开头的行,我下面的两个表达式:

表达式1"^From|Subject|Data: "

表达式2"^(From|Subject|Data): "

哪一个是我想要的?

很明,表达式1果不是我想要的果,它匹配的将是:From或者Subjec或者Data: ,表达式2使用括符,就能足我的需要。



单词边

可以匹配出在行首和行尾的字符,那如果我想定位的不仅仅是行首或者行尾呢?我需要引入单词边界符号,单词边界符号是:"\b",斜杠不可省略,否则变成匹配字母b。使用单词边界符号,我可以定位匹配的位置必在一个单词始或者尾部分,而不是在单词的中。例如:"\bis\b"表达式在字符串"This is a cat."中将匹配单词"is"而不会匹配单词"This"中的"is"



字符串界符号

除了上述的位置符号,如果我要匹配的是整个字符串(含多个单词)那可以使用下面的两个符号:

\A :
表示字符串的

\z :
表示字符串的

表达式:"\AThis is a cat\z"将匹配个字符串"This is a cat"

使用界定位符号,里要提到一个重要的概念,那就是单词字符,单词字符表示可以构成单词的字符,它[a-zA-Z0-9]中的任意一个字符。所以上面的表达式也会在句子"This is a cat."得到匹配。匹配的果不包含句号。





数量符号

看表达式:"Colou?r", 个表达式中出了我们还没有见过号,(号和文件名称匹配的号意不同),它表示符号前面的一个字符可以被重的次数,"?"表示0次或者1次,前面的表达式中号表示u可以出01次,所以它将匹配"Color"或者"Colour"

下面是其他的重数量符号:

+
:表示1次或者多次

*
:表示0次或者多次

例如我要表示一或多个空格,我可以写表达式:" +";



如果要表示具体次数呢?我引入花括符{}

{n} : n
是具体的数字,表示重n次。

{n,m}:
表示最少那次,最多m次。



些符号都限定了符号前面一个字符的匹配次数。但是如果你想重多个字符,比如一个单词,那么办?我再次使用括号,前面我括号作为选项的范符号,里是括的另外一使用方法,它被表示一个,例如表达式:“(this)"里的this就是一个,那么问题就好了,重数量符号可以用来表示它前面一个的重次数。



在回到找重复单词问题,假如我要找到“the the”,根据我迄今止学到的知,我可以写出表达式:

"\bthe +the\b"

表达式的意思是匹配两个the有一个或多个空格隔

,我们还可以写成:

"\b(the +){2}"



但是如果要找全部可能的重复单词呢?我目前的知识还不足以解决问题,下面我反向引用的概念,我看到括号可以作为组界,一个表达式中可以有多个被括号限定的,根据它的次序,缺省的被分配了一个号,第一个出1号,依次推。那反向引用就是可以在之后的表达式的位置上是使用"\n"来引用n是被引用的号。反向引用就像是程序中的量一,下面我看具体的例子:

前面的单词表达式,在我采用反向引用可以写做:

"\b(the) +\1\b"

在,如果我要匹配所有的重复单词,我就可以改写表达式
"\b([a-zA-Z]+) +\1\b"



最后一个问题是,如果我要匹配的字符是正表达式中的符号,怎么办,使用转义符号"\", 例如如果你要匹配一个小数点,那你可以:"\."要注意的是如果在程序中使用表达式那"\"也要按照字符串的"\\"或者在表达式前面加@



本章仅仅是提供一个于正表达式的基,它只是其中的部分,我们还西要学将在后面的章中一一介。其,正表达式的学并不,你需要的是耐心和践,如果你想精通它的。或有人:“我不想知道汽细节,我只想学会怎么开车。”如果你也是这样想的,那,你永也不知道怎使用正表达式来解决你的问题而,你也永不会懂得正表达式的真正的大。

posted on 2007-09-12 21:44  Game_over  阅读(409)  评论(0)    收藏  举报