換個角度理解正規表示式

2021-06-18 19:56:47 字數 3769 閱讀 8934

、作者資訊和本宣告。否則將追究法律責

其實linux

系統中處理文字的工具還有很多,功能也遠比我們所能想象到的任何工具都要強大。要想真正掌握它們,就必須要掌握一項基本技能

——正規表示式。

正規表示式已經無處不在了,無論是網路文章,還是很多圖書,亦或是教材也都在講解正規表示式,我們也堅信正在讀本書的你也早已熟稔正規表示式的運用。但是,我們依然要介紹它,只是換了乙個角度,以期望初學者能有乙個好的開端,行家裡手們能夠加深入的理解它,因為要熟練使用

linux

是離不開正規表示式。

對於初學者來講,一定會追問到底什麼是正規表示式。這是乙個很難回答的問題。但是我們可以通過乙個應用例項來讓大家明白。一般地,我們在處理字串的時候後有需要判斷是否存在某個子串的情況,比如要在字串

「prefix=/usr

」中來判斷是否擁有

「prefix=

」這個字串,可以使用逐一比對的方式來完成這個功能。這看起來很好,而且屢試不爽。還能進一步演進演算法,實現提取諸如

「prefix」的

「值」這樣的需求。顯然只需要判斷字串中有

「prefix=

」這個子串並確認它的位置就能夠提取出

「/usr

」這個子串了。看來變數取值演算法也是很「簡單

」的啊!但是別驕傲,當你遇到

「exec-prefix=/libexec prefix=/usr

」這樣的字串時,你怎麼取

「prefix

」的值呢?你會說,稍微變化一下演算法就行了。那遇到的字串更複雜怎麼辦?對於這類需求,我們可以變換一下思路,即找到

「k=v

」這樣形式的子串會更好。或許現在你覺得思路又開闊了。但是別著急,還有更複雜的在等著你。比如字串

「3.1416 * 100 ^ 2

」,要提取出所有數字。似乎你又有思路了,無外乎提取連續的0至

9,附帶+、

-號以及「.

」的字串,但是這就能完成任務了?如果再變成

「3.1416 * 1.3e2 ^ 2

」這樣了呢?反正變化很多。如果你要還是保持前面的思路,我保證你使用幾十萬行**的

if-else

都滿足不了需求。估計你現在一定會想,如果有一門語言只需要編寫少量的**就能夠滿足上面的所有需求的話,一定要學會它。這樣你就不怕老闆在這個地方的各種刁難。那我告訴你,還真有一門這樣的語言,它就是

——正規表示式。一些簡單的正規表示式,就能夠滿足上面的這些需求,比如:

prefix=

[ \t]*[a-za-z]+=[ \t]*[a-za-z/]+[ \t]*

[+-]?[0-9]+(\.[0-9]*)?([ee][+-]?[0-9]+)?

我們說上面的這些方方塊塊、花花草草就是正表示式了,它們具體都是什麼含義呢?

為了搞清楚這個問題,我們首先要對正規表示式所要處理的文字進行一下精確定義。這個定義是:文字是指字串的集合,其中的字元來自於乙個有限的字元集合。也就是說,文字是由乙個有限的字符集構成的,但是文字本身既可以是有窮集合,也可以是無窮集合。就比如屬於文字的源**檔案,就是滿足某種語言語法的全體字串的集合,但是不同的源**全部算在一起顯然就是乙個無窮的集合。當然,也可以有非常簡單的文字,比如只含有乙個字母「a

」的文字,如果用集合了表示的話就是{

a}。按照這個定義,正規表示式就是來描述任意文字的一種特殊表示式,而且擁有兩個基本要素: l

表示式ε

表示乙個文字,僅包含乙個長度為

0的字串,也可以理解為{

null

}。通常將

null記作ε

; l對字符集中任意字元

a,表示式

a表示僅有乙個字元

a的文字,即{a}

以及三種基本運算規則: l

兩個正規表示式的並,記作

x|y,表示的文字是正規表示式

x所表示的文字與正規表示式

y所表示的文字的並集。比如

a|b所得的文字就是

,類似於加法; l

兩個正規表示式的連線,記作

xy,表示的文字是將

x文字中的每個字串後面連線上

y文字中的每乙個字串之後,再把所有這種連線的結果組成一種新的文字。比如

x=a|b

,y=c|d

,那麼xy

所表示的文字就是{ac,

bc,ad,

bd}。因為x是{

a, b

},而y

是{c,d

},連線運算取

x文字的每個字串接上

y文字的每乙個字串,最後得到了

4種連線結果。這類似於乘法; l

乙個正規表示式的克林閉包,記作

x*,表示分別將0個、

1個、2個

……n個x

與自己連線,然後再把所有這些求並。也就是說

x*=ε|x|xx|***|

……。比如

a*這個正規表示式,就表示的是無窮文字{ε,

a,aa,

aaa,

……}。這相當於任意次重複乙個語言。

以上三種運算寫在一起時,克林閉包的優先順序高於連線運算,而連線運算的優先順序高於並運算。這就是正規表示式的全部規則。完全不難理解吧?

在正規表示式的實際使用中,如果只是提供上述三種運算很多時候會使得正規表示式被書寫的十分複雜,為了簡化正規表示式又引入了一些擴充套件運算。這些擴充套件運算都是基於三種基本運算的,它們是: l

方括號表示括號內的字元做並運算,同時支援範圍描述符「-」

。比如[abcd]

就等於a|b|c|d

,等價於

[a-d]。

l由於方括號中支援範圍描述「-

」,如果要使用「-

」字元,則需要將它放在方括號的開頭,如

[-abc]

等於-|a|b|c。

l方括號中以

^字元開頭,表示在字符集中排除方括號中的所有字元之後,所剩字元的並運算。比如

[^ab]

則表示除了

ab以外的所有字元求並。 l

x?表示

x|ε。這就代表

x與空字串之間可選。 l

x+表示

xx*。這等於限制了

x至少要重複1次。

現在我們就可以理解一下我們前面給出的這幾個正規表示式了。

第乙個正規表示式是

「prefix=」

,這就是乙個連線運算,由「p」

、「r」

、「e」

、「f」

、「i」

、「x」

、「=」

這幾個字元連線而成。

第二個正規表示式則是提取出

「k=v

」這樣形式的子串,取「=

」號右側子串就等同於取值了。而且限定了用空格來區分「

k=v」

結構的邊界。

[ \t]

就是描述空格的正規表示式。

第三個正規表示式是提取數字,包含浮點數和科學計數法。比較困惑的是

「()」

圓括號的出現。這是因為很多正規表示式工具預設都使用單一字元作為字串邊界,為了擴大子串的邊界,可以使用

「()」

來明確限定,所以也被稱為子表示式。但是這種子表示式並不屬於標準正規表示式的範疇,所以會遇到不支援的情況。

好了,這部份的內容就算結束了,這是純理論的,希望這些內容能夠幫助到大家。本書的後續內容還會遇到一些有關正規表示式的內容,那些就更加偏重於實踐了。本書之所以要這樣組織,主要是考慮到正規表示式的派系過於繁雜,不同情況下所使用的工具對正規表示式派系的支援可能不太一樣,只有遇到合適的場景才能更好的體會的這些差異來。其實接下來的內容就已經是這樣的了。

正規表示式理解

正規表示式問題 string regex 1 d 2 0 4 d 25 0 5 1 9 d 1 9 1 d 2 0 4 d 25 0 5 1 9 d d 1 d 2 0 4 d 25 0 5 1 9 d d 1 d 2 0 4 d 25 0 5 1 9 d d 幫我把這一段解釋下,怎麼看都看不懂 驗...

理解正規表示式

1.概念 正規表示式 regular expression 是一種文字模式,包括普通字元 例如,a 到 z 之間的字母 和特殊字元 稱為 元字元 正規表示式使用單個字串來描述 匹配一系列匹配某個句法規則的字串。這裡用php中的正規表示式說明,其他語言可參考 1 2 pattern test 3 st...

正規表示式之理解

1.正規表示式語法字元 說明 將下一字元標記為特殊字元 文字 反向引用或八進位制轉義符。例如,n 匹配字元 n n 匹配換行符。序列 匹配 匹配 匹配輸入字串開始的位置。如果設定了regexp物件的multiline屬性,還會與 n 或 r 之後的位置匹配。匹配輸入字串結尾的位置。如果設定了rege...