[王垠系列]為什么需要正則表達(dá)式

學(xué)習(xí)Unix最開(kāi)頭,大家都學(xué)過(guò)正則表達(dá)式(regexp)??墒怯袥](méi)有人考慮過(guò)我們為什么需要正則表達(dá)式?

正則表達(dá)式本來(lái)的初衷是用來(lái)從無(wú)結(jié)構(gòu)的字符串中提取信息,殊不知這正好是Unix的缺陷所在。Unix用無(wú)結(jié)構(gòu)的字符串來(lái)表示數(shù)據(jù),導(dǎo)致了諸多復(fù)雜的基于regexp的軟件的誕生。sed, AWK, Perl,?...?都是為了同樣的目的來(lái)到這個(gè)世界上的。如果不是因?yàn)閁nix用字符串來(lái)表示數(shù)據(jù),我們就會(huì)擁有按數(shù)據(jù)結(jié)構(gòu)類型的直接存儲(chǔ),而不需要折騰regexp。正則表達(dá)式有它自己的價(jià)值(針對(duì)自然語(yǔ)言),但是我們其實(shí)不需要把它應(yīng)用到程序語(yǔ)言和操作系統(tǒng)里面。

正則表達(dá)式本身用一個(gè)字符串來(lái)表示,這帶來(lái)另外一些問(wèn)題。因?yàn)檎齽t表達(dá)式的本質(zhì)不是字符串,而是一個(gè)數(shù)據(jù)結(jié)構(gòu)。學(xué)過(guò)計(jì)算理論的人可能知道這個(gè)數(shù)據(jù)結(jié)構(gòu)叫做NFA(nondeterministic finite automaton,非確定性有限自動(dòng)機(jī))。所有的數(shù)據(jù)結(jié)構(gòu)應(yīng)該由程序語(yǔ)言本身來(lái)表示,就像用Java構(gòu)造一個(gè)對(duì)象用 new ClassA("a")?一樣。但是正則表達(dá)式強(qiáng)迫你把這個(gè)簡(jiǎn)單的構(gòu)造函數(shù)調(diào)用寫(xiě)成一個(gè)字符串。所以在這個(gè)比方之下,你得寫(xiě)成?"new ClassA(\"a\")"。這樣當(dāng)你想要組合這些表達(dá)式的時(shí)候就發(fā)現(xiàn),正則表達(dá)式幾乎都是不可組合(compose)的。你幾乎不可能不能把兩個(gè)regexp的變量A和B安全拼接成一個(gè),比如用Java的字符串拼接A+B。因?yàn)槟悴恢肋@兩個(gè)字符串拼在一起之后,那些稀奇古怪的符號(hào)會(huì)出現(xiàn)什么交叉反應(yīng),使得最后的識(shí)別的東西根本不是你想要的。

在正則表達(dá)式中,由于正則表達(dá)式本身的構(gòu)造函數(shù)與數(shù)據(jù)本身合并到一起,我們不得不對(duì)某些“特殊字符”進(jìn)行escape。這些特殊字符,其實(shí)是用來(lái)描述NFA的記號(hào),它們屬于更高一層的語(yǔ)言。可是在正則表達(dá)式里,它們與NFA節(jié)點(diǎn)里的字符混為一談。比如很簡(jiǎn)單的一個(gè)block comment的正則表達(dá)式,卻要寫(xiě)成這個(gè)樣子:

"/\\*([^\\*]|[^/])*\\*/"

顯然這樣的表達(dá)式很容易出錯(cuò)。?如果我們用程序語(yǔ)言的表達(dá)式來(lái)構(gòu)造這個(gè)表達(dá)式,它應(yīng)該是這樣:

在這個(gè)我自己設(shè)計(jì)的Scheme表達(dá)式里,以@開(kāi)頭的標(biāo)識(shí)符都是構(gòu)造函數(shù)。其中?@...是構(gòu)造sequence,@*?是構(gòu)造一個(gè)zero-or-more的匹配,@!構(gòu)造一個(gè)否定匹配。這個(gè)表達(dá)式是說(shuō):“以?/?*?開(kāi)頭,接著零個(gè)或者多個(gè)不是?*?/?的字符,最后接著一個(gè)?*?/。這樣一來(lái)清晰明了,什么表達(dá)式在什么“層次”都很清楚,不需要什么反斜杠escape,而且這樣的表達(dá)式可以compose。比如:

定義這三個(gè)表達(dá)式之后,我們之后可以用像?(@... reg1 (@or reg2 reg3))?這樣的表達(dá)式來(lái)連接3個(gè)不同的表達(dá)式,構(gòu)造出更大的表達(dá)式。這樣的構(gòu)造可以無(wú)限的擴(kuò)展。從這里以及以往的經(jīng)驗(yàn),我總結(jié)出一個(gè)普遍適用的程序設(shè)計(jì)的教訓(xùn):盡量不要把多個(gè)層次的語(yǔ)言“壓縮”到一層。我們也看到正則表達(dá)式與“Unix哲學(xué)”有很大關(guān)系。我沒(méi)有考古,所以不知道孰先孰后,但是它們肯定有直接的因果關(guān)系。兩者都是Unix復(fù)雜性的來(lái)源。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容