1. 程式人生 > >正則表示式的語法和簡單應用

正則表示式的語法和簡單應用

在Java中,藉助於String類的一系列方法,我們已經可以對字串做簡單的處理:比如求子串、查詢字元、格式化字串、字串替換等等。正則表示式則提供了更為強大的對字串的處理操作,是一種強大而靈活的文字處理工具。

正則表示式對文字的匹配流程如下圖所示:

簡單的說,正則表示式就是以特定的語法規則描述一個字串:如果待匹配文字的內容符合正則表示式的內容,則匹配成功;否則匹配失敗。

正則表示式的語法

正則表示式的語法主要分為:單個字元、字符集、邏輯操作符、捕獲組、數量詞、邊界匹配符等若干部分。

一、單個字元

1、一般的字元:這裡的字元包括字母(大小寫)、數字、符號等,語法原則是匹配自身。比如正則表示式為“abc”,那麼有且只能是“abc”文字才能匹配成功。

2、任意字元.:.字元語法原則是與任意字元匹配。比如正則文字“a.c”可以匹配“axc”文字。

3、轉義字元\:使後面的一個字元具有特定的意義。語法原則與一般的轉義字元用法一致,比如"a\.c"則只能與“a.c”匹配。

二、字符集

1、一般字符集[...]:注意,字符集並不表示一個集合全部內容,表示的是這個集合中的任一一個元素的含義。比如,"[abc]"表達的含義與"abc"完全不同,前者表達abc中任一一個字元的含義。一般字符集的語法規則是方括號[ ]內顯示地表達元素集合:可以選擇逐一列出,如[abcde];還可以選擇用-符號表示範圍,比如[a-z]表示小寫英文字母的集合中的任意一個字元。特別地,如果範圍比較分散而元素又太多了不好一一列舉,可以取集合中補集的概念,在[ ]中開始位置用^表示“排除”、“取反”、“取補集”的含義,比如[^abc]表示除了abc以外的任意一個字元。

2、預定義字符集:為了方便使用,不需要每次都需要自己用[...]語法表示,正則表示式引擎預先提供了一些字符集,主要有:

①\d:相當於“[0-9]”,即數字字元。

②\s:相當於“[\t\r\n\f]”,即空白字元。

③\w:相當於"[a-zA-Z0-9]",即單詞字元。

④以上三種字符集,分別取補集,為了方便記憶用對應大寫字母表達,即得到\D(非數字字元) \S(非空白字元) \W(非單詞字元)等字符集。

切記:無論是一般字符集[...]還是預定義字符集,表達的都是“一個”字元的概念:一個字元集合中任意一個字元!

三、邏輯操作符

邏輯操作符指的是,如果一個正則表示式中既有字元又有字符集還有其他的語法元素時,這些元素之間的邏輯關係是怎樣的。主要有:

1、XY:順序結構,Y跟在X後面,所以語法原則是先檢查X,如果匹配再檢查Y。

2、X|Y:“或”關係,左右兩個表示式只需要滿足一個即表示文字匹配成功。所以,如果X匹配成功,則直接跳過Y的檢查。

四、捕獲組(capturing group)

捕獲組非常容易與字符集混淆:首先,兩者形式不同:前者是(...),後者是[...]。然後,兩者含義不同:前者表示的是實打實的集合整體,後者則是整體中的任意一個元素。

捕獲組語法非常簡單:圓括號(...),比如"a(bc)d"只能與"abcd"匹配成功。

切記,正則文字如果使用了捕獲組,圓括號是不參與匹配的,它只是正則的語法元素而已!

可以瞭解一下捕獲組幾個重要的用法:

捕獲組的編號:捕獲組是可以巢狀的,這就像數學表示式中圓括號可以"一對套一對"一樣。捕獲組可以因此可以編號:編號從0開始(即全部正則文字內容),最外層括號包含的內容為第1組,依次按層次編號即可。比如有一個正則文字"a(b(c)d(e))f",第0組為abcdef,第1組為bcde,第2組為c 和 e。

捕獲組的命名:除了編號外,還可以給捕獲組命名,命名語法為:(?P<name>...),其實就是在捕獲組內容前面加上?P<name>即可,其中的name即為該組的組名。

捕獲組的編號和命名,本質都是為了在一個正則文字中將多個捕獲組區分開。那麼區分不同的捕獲組的意義在哪?就是為了引用捕獲組。因為捕獲組代表某個字元集合整體,而我們希望正則表示式儘量簡潔,所以在不同的地方使用同樣的捕獲組的時候,用引用代替重複的文字。具體如下:

捕獲組的編號引用:引用語法為"\x".  其中,x為想引用的捕獲組編號。比如,對於正則文字"(abc)d\1",“abcdabc”文字才能與它匹配。顯然這裡\1是對第1組的引用。

捕獲組的名稱引用:引用語法為"(?P=name)". 其中,name為引用的捕獲組名稱,由於捕獲組編號是系統自動追加的,而捕獲組名稱是使用者自己新增的,所以必須保證該名稱確實被命名一個捕獲組過。另外,這裡的圓括號與?都不能省略。比如:正則文字"a(?P<happy>bc)d(?P=happy)",與其匹配的文字應當為"abcdbc"。

捕獲組相當於將若干個一般字元與其他部分隔離開,但是這種隔離並非是沒有意義的;通過這種隔離可以實現特定的匹配含義。稍後,說明這一點。

五、數量詞

 至此,大家可能會有疑惑:我們目前表示的正則表示式,與其匹配的文字都是唯一確定的,那我們為什麼不直接用String表示字串得了?當有了數量詞後,正則表示式才具有了真正的強大的靈活性。數量詞可以用於字元(包括單個字元與字符集)後面或者捕獲組後面。

如果數量詞用於單個字元或字符集後面,這二者表達的都是一個字元的概念,所以數量詞作用域為前面這一個字元!如果數量詞用於捕獲組後面,數量詞作用域為整個捕獲組整體字元集合。

1、X* 表示X可以出現0次或多次。對於正則文字"ab*",則文字"a"、"ab"、"abb"都可以與其匹配。對於正則文字“a(bc)*”,則文字"a"、"abc"、"abcbc"可以與其匹配。這裡的兩個例子也剛好可以看出數量詞對單個字元/字符集和捕獲組的不同作用域(其實只需將捕獲組看作是一個整體即可)。

2、X+ 表示X出現一次或多次。

3、X?    表示X出現0次或者1次。

4、{m} 表示X出現m次。

5、{m,n} 表示X出現次數在m到n次之間。若省略m,則變成{,n},表示X出現次數在0到n之間。如果省略n,變成{m,},表示X出現次數在m到無限次之間。注意,省略m或n時,花括號中的逗號切不可省略,否則就變成上一種情況了。

六、邊界匹配符

邊界匹配符用來控制匹配文字時的匹配位置進一步提升了正則表示式的靈活性,:比如在開頭匹配或在末尾匹配等。這裡略。

正則表示式具有強大的靈活性,同一個正則文字,可能有多個甚至無數個文字可以與其匹配成功。但是很多情況下,我們不需要這麼多匹配成功的文字。這涉及到一個正則匹配“貪婪型”、“非貪婪型”的問題。

正則匹配過程預設是貪婪型的:即貪婪正則表示式會在已經找到一個符號匹配的文字後繼續往下吸收文字。

可以手動將正則表示式指定為非貪婪型,方式是在數量詞後面加上?。這樣非貪婪表示式會匹配滿足表示式的最少字元數的文字。即*?  +?  ??  {m,n}?等。

正則表示式的簡單應用

正則表示式對於文字處理而言非常強大,這裡只介紹簡單的應用。

1、匹配檢查:String類的例項方法matchs(String regex)可用來檢查字串是否匹配引數中的正則表示式。

2、字串分割:String類的例項方法split(String regex)可用來切分字串,返回一個切分後的字串陣列。該方法遇到符合正則表示式內容的內容時,進行切割,最後結果是忽略了該部分內容,原本的字串變成一段段的子串,以字串陣列的形式返回。

3、字串替換:儘管String類已經提供了replace(String target,String replacement)方法用來進行字串替換的操作。但是使用正則表示式更靈活,主要有以下兩種方式:

①replaceAll(String regex,String replacement)

②replaceFirst(String regex,String replacement)

這兩種方法都是String類的例項方法,作用都是尋找符合引數一正則表示式內容的部分,用引數二的字串替換。二者的區別在於後者只替換第一次匹配成功的文字,前者替換全部匹配成功的文字。

————————over。