正則表達(dá)式(REs)通常被錯(cuò)誤地認(rèn)為是只有少數(shù)人理解的一種神秘語(yǔ)言。在表面上它們確實(shí)看起來(lái)雜亂無(wú)章,如果你不知道它的語(yǔ)法,那么它的代碼在你眼里只是一堆文字垃圾而已。實(shí)際上,正則表達(dá)式是非常簡(jiǎn)單并且可以被理解。讀完這篇文章后,你將會(huì)通曉正則表達(dá)式的通用語(yǔ)法。
支持多種平臺(tái)
正則表達(dá)式最早是由數(shù)學(xué)家Stephen Kleene于1956年提出,他是在對(duì)自然語(yǔ)言的遞增研究成果的基礎(chǔ)上提出來(lái)的。具有完整語(yǔ)法的正則表達(dá)式使用在字符的格式匹配方面上,后來(lái)被應(yīng)用到熔融信息技術(shù)領(lǐng)域。自從那時(shí)起,正則表達(dá)式經(jīng)過(guò)幾個(gè)時(shí)期的發(fā)展,現(xiàn)在的標(biāo)準(zhǔn)已經(jīng)被ISO(國(guó)際標(biāo)準(zhǔn)組織)批準(zhǔn)和被Open Group組織認(rèn)定。
正則表達(dá)式并非一門(mén)專用語(yǔ)言,但它可用于在一個(gè)文件或字符里查找和替代文本的一種標(biāo)準(zhǔn)。它具有兩種標(biāo)準(zhǔn):基本的正則表達(dá)式(BRE),擴(kuò)展的正則表達(dá)式(ERE)。ERE包括BRE功能和另外其它的概念。
許多程序中都使用了正則表達(dá)式,包括xsh,egrep,sed,vi以及在UNIX平臺(tái)下的程序。它們可以被很多語(yǔ)言采納,如HTML 和XML,這些采納通常只是整個(gè)標(biāo)準(zhǔn)的一個(gè)子集。
比你想象的還要普通
隨著正則表達(dá)式移植到交叉平臺(tái)的程序語(yǔ)言的發(fā)展,這的功能也日益完整,使用也逐漸廣泛。網(wǎng)絡(luò)上的搜索引擎使用它,e-mail程序也使用它,即使你不是一個(gè)UNIX程序員,你也可以使用規(guī)則語(yǔ)言來(lái)簡(jiǎn)化你的程序而縮短你的開(kāi)發(fā)時(shí)間。
正則表達(dá)式101
很多正則表達(dá)式的語(yǔ)法看起來(lái)很相似,這是因?yàn)槟阋郧澳銢](méi)有研究過(guò)它們。通配符是RE的一個(gè)結(jié)構(gòu)類型,即重復(fù)操作。讓我們先看一看ERE標(biāo)準(zhǔn)的最通用的基本語(yǔ)法類型。為了能夠提供具有特定用途的范例,我將使用幾個(gè)不同的程序。
字符匹配
正則表達(dá)式的關(guān)鍵之處在于確定你要搜索匹配的東西,如果沒(méi)有這一概念,Res將毫無(wú)用處。
每一個(gè)表達(dá)式都包含需要查找的指令,如表A所示。
Table A: Character-matching regular expressions
|
操作
|
解釋
|
例子
|
結(jié)果
|
.
|
Match any one character
|
grep .ord sample.txt
|
Will match “ford”, “l(fā)ord”, “2ord”, etc. in the file sample.txt.
|
[ ]
|
Match any one character listed between the brackets
|
grep [cng]ord sample.txt
|
Will match only “cord”, “nord”, and “gord”
|
[^ ]
|
Match any one character not listed between the brackets
|
grep [^cn]ord sample.txt
|
Will match “l(fā)ord”, “2ord”, etc. but not “cord” or “nord”
|
|
|
grep [a-zA-Z]ord sample.txt
|
Will match “aord”, “bord”, “Aord”, “Bord”, etc.
|
|
|
grep [^0-9]ord sample.txt
|
Will match “Aord”, “aord”, etc. but not “2ord”, etc.
|
重復(fù)操作符
重復(fù)操作符,或數(shù)量詞,都描述了查找一個(gè)特定字符的次數(shù)。它們常被用于字符匹配語(yǔ)法以查找多行的字符,可參見(jiàn)表B。
Table B: Regular expression repetition operators
|
操作
|
解釋
|
例子
|
結(jié)果
|
?
|
Match any character one time, if it exists
|
egrep “?erd” sample.txt
|
Will match “berd”, “herd”, etc. and “erd”
|
*
|
Match declared element multiple times, if it exists
|
egrep “n.*rd” sample.txt
|
Will match “nerd”, “nrd”, “neard”, etc.
|
+
|
Match declared element one or more times
|
egrep “[n]+erd” sample.txt
|
Will match “nerd”, “nnerd”, etc., but not “erd”
|
{n}
|
Match declared element exactly n times
|
egrep “[a-z]{2}erd” sample.txt
|
Will match “cherd”, “blerd”, etc. but not “nerd”, “erd”, “buzzerd”, etc.
|
{n,}
|
Match declared element at least n times
|
egrep “.{2,}erd” sample.txt
|
Will match “cherd” and “buzzerd”, but not “nerd”
|
{n,N}
|
Match declared element at least n times, but not more than N times
|
egrep “n[e]{1,2}rd” sample.txt
|
Will match “nerd” and “neerd”
|
錨
錨是指它所要匹配的格式,如圖C所示。使用它能方便你查找通用字符的合并。例如,我用vi行編輯器命令:s來(lái)代表substitute,這一命令的基本語(yǔ)法是:
s/pattern_to_match/pattern_to_substitute/
?
Table C: Regular expression anchors
|
操作
|
解釋
|
例子
|
結(jié)果
|
^
|
Match at the beginning of a line
|
s/^/blah /
|
Inserts “blah “ at the beginning of the line
|
$
|
Match at the end of a line
|
s/$/ blah/
|
Inserts “ blah” at the end of the line
|
\<
|
Match at the beginning of a word
|
s/\</blah/
|
Inserts “blah” at the beginning of the word
|
|
|
egrep “\<blah” sample.txt
|
Matches “blahfield”, etc.
|
\>
|
Match at the end of a word
|
s/\>/blah/
|
Inserts “blah” at the end of the word
|
|
|
egrep “\>blah” sample.txt
|
Matches “soupblah”, etc.
|
\b
|
Match at the beginning or end of a word
|
egrep “\bblah” sample.txt
|
Matches “blahcake” and “countblah”
|
\B
|
Match in the middle of a word
|
egrep “\Bblah” sample.txt
|
Matches “sublahper”, etc.
|
間隔
Res中的另一可便之處是間隔(或插入)符號(hào)。實(shí)際上,這一符號(hào)相當(dāng)于一個(gè)OR語(yǔ)句并代表|符號(hào)。下面的語(yǔ)句返回文件sample.txt中的“nerd” 和 “merd”的句柄:
egrep “(n|m)erd” sample.txt
間隔功能非常強(qiáng)大,特別是當(dāng)你尋找文件不同拼寫(xiě)的時(shí)候,但你可以在下面的例子得到相同的結(jié)果:
egrep “[nm]erd” sample.txt
當(dāng)你使用間隔功能與Res的高級(jí)特性連接在一起時(shí),它的真正用處更能體現(xiàn)出來(lái)。
一些保留字符
Res的最后一個(gè)最重要特性是保留字符(也稱特定字符)。例如,如果你想要查找“ne*rd”和“ni*rd”的字符,格式匹配語(yǔ)句“n[ei]*rd”與“neeeeerd” 和 “nieieierd”相符合,但并不是你要查找的字符。因?yàn)椤?’(星號(hào))是個(gè)保留字符,你必須用一個(gè)反斜線符號(hào)來(lái)替代它,即:“n[ei]\*rd”。其它的保留字符包括:
-
^ (carat)
-
. (period)
-
[ (left bracket}
-
$ (dollar sign)
-
( (left parenthesis)
-
) (right parenthesis)
-
| (pipe)
-
* (asterisk)
-
+ (plus symbol)
-
? (question mark)
-
{ (left curly bracket, or left brace)
-
\ backslash
一旦你把以上這些字符包括在你的字符搜索中,毫無(wú)疑問(wèn)Res變得非常的難讀。比如說(shuō)以下的PHP中的eregi搜索引擎代碼就很難讀了。
eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$",$sendto)
你可以看到,程序的意圖很難把握。但如果你拋開(kāi)保留字符,你常常會(huì)錯(cuò)誤地理解代碼的意思。
總結(jié)
在本文中,我們揭開(kāi)了正則表達(dá)式的神秘面紗,并列出了ERE標(biāo)準(zhǔn)的通用語(yǔ)法。如果你想閱覽Open Group組織的規(guī)則的完整描述,你可以參見(jiàn):
Regular Expressions
,歡迎你在其中的討論區(qū)發(fā)表你的問(wèn)題或觀點(diǎn)。
|