正則表達式(9):擴展正則表達式
- 小結
本博文轉載自
前文中一直在說,在Linux中,正則表達式可以分為”基本正則表達式”和”擴展正則表達式”。
我們已經認識了”基本正則表達式”,現在,我們來認識一下”擴展正則表達式”。
有了之前的基礎,學習”擴展正則表達式”簡直不要太輕松。
之前說過,有些符號是通用的,不管是在”基本正則表達式”中,還是在”擴展正則表達式”中,這些通用的符號所表達的意思都是相同的。
那么,我們先來看看哪些符號是通用的,看完之后你會信心大增,如下字符都是通用的:
. 表示任意單個字符。
* 表示前面的字符連續出現任意次,包括0次。
.* 表示任意長度的任意字符,與通配符中的*的意思相同。
\ 表示轉義符,當與正則表達式中的符號結合時表示符號本身。
[ ]表示匹配指定范圍內的任意單個字符。
[^ ]表示匹配指定范圍外的任意單個字符。[[:alpha:]] 表示任意大小寫字母。
[[:lower:]] 表示任意小寫字母。
[[:upper:]] 表示任意大寫字母。
[[:digit:]] 表示0到9之間的任意單個數字(包括0和9)。
[[:alnum:]] 表示任意數字或字母。
[[:space:]] 表示任意空白字符,包括"空格"、"tab鍵"等。
[[:punct:]] 表示任意標點符號。
[^[:alpha:]] 表示單個非字母字符。
[^[:lower:]] 表示單個非小寫字母字符。
[^[:upper:]] 表示單個非大寫字母字符。
[^[:digit:]] 表示單個非數字字符。
[^[:alnum:]] 表示單個非數字非字母字符。
[^[:space:]] 表示單個非空白字符。
[^[:punct:]] 表示單個非標點符號字符。
[0-9]與[[:digit:]]等效。
[a-z]與[[:lower:]]等效。
[A-Z]與[[:upper:]]等效。
[a-zA-Z]與[[:alpha:]]等效。
[a-zA-Z0-9]與[[:alnum:]]等效。
[^0-9]與[^[:digit:]]等效。
[^a-z]與[^[:lower:]]等效。
[^A-Z]與[^[:upper:]]等效
[^a-zA-Z]與[^[:alpha:]]等效
[^a-zA-Z0-9]與[^[:alnum:]]等效^:表示錨定行首,此字符后面的任意內容必須出現在行首,才能匹配。
$:表示錨定行尾,此字符前面的任意內容必須出現在行尾,才能匹配。
^$:表示匹配空行,這里所描述的空行表示"回車",而"空格"或"tab"等都不能算作此處所描述的空行。
^abc$:表示abc獨占一行時,會被匹配到。
\<或者\b :匹配單詞邊界,表示錨定詞首,其后面的字符必須作為單詞首部出現。
\>或者\b :匹配單詞邊界,表示錨定詞尾,其前面的字符必須作為單詞尾部出現。
\B:匹配非單詞邊界,與\b正好相反。
上述符號,在基本正則表達式中與擴展正則表達式中的用法完全相同。
有沒有感覺,70%都是通用的,那么我們來動手試試。
在總結grep命令時,我們提到過,grep命令默認只支持基本正則表達式,如果想要讓grep命令能夠支持擴展的正則表達式,則需要使用”-E”選項,示例如下
上圖中,grep命令使用了”-E”選項,表示grep命令會把”正則表達式”中的符號當成”擴展正則表達式”去理解,而不再使用默認的”基本正則表達式”。
但是由于”[A-Z]”是通用的,所以,不管是否使用擴展正則表達式,”[A-Z]”都表示單個大寫字母。
剛才說過,70%的符號都是通用的,那么剩下的30%呢?
其實,剩下的30%也都差不多,與基本正則表達式相比,反而更加簡單了,不信?我們就來看看。
在基本正則表達式中,{n} 表示前面的字符連續出現n次,將會被匹配到。
在擴展正則表達式中,{n} 表示前面的字符連續出現n次,將會被匹配到。
在基本正則表達式中,( ) 表示分組,(ab) 表示將ab當做一個整體去處理。
在擴展正則表達式中,( ) 表示分組,(ab) 表示將ab當做一個整體去處理。
在寫法上,”擴展正則表達式”的寫法是不是更加簡練呢?示例如下
如上圖所示,當使用”擴展正則表達式”時,在”書寫”方面,反而省力不少,最終匹配到的文本卻是相同的,是不是很方便?
看完了上述示例,我想你對擴展正則表達式應該已經有了一個初步的印象了。
那么,我們就來介紹一下,有哪些符號在”擴展正則表達式”中變得更加簡練了。
在擴展正則表達式中:
( ) 表示分組
(ab) 表示將ab當做一個整體去處理。
\1 表示引用整個表達式中第1個分組中的正則匹配到的結果。
\2 表示引用整個表達式中第2個分組中的正則匹配到的結果。
? 表示匹配其前面的字符0或1次
- 表示匹配其前面的字符至少1次,或者連續多次,連續次數上不封頂。
{n} 表示前面的字符連續出現n次,將會被匹配到。
{x,y} 表示之前的字符至少連續出現x次,最多連續出現y次,都能被匹配到,換句話說,只要之前的字符連續出現的次數在x與y之間,即可被匹配到。
{,n} 表示之前的字符連續出現至多n次,最少0次,都會陪匹配到。
{n,}表示之前的字符連續出現至少n次,才會被匹配到。
看了上述總結以后,是不是已經想要放棄使用”基本正則表達式”了呢?因為與之相比,擴展正則表達式才更符合我們這些懶人的習慣,而且,擴展正則表達式的可讀性也更高,畢竟很多符號少了前面的”\”,可讀性就變強了。
擴展正則表達式中,還有一個常用的符號,它就是”|” (在基本正則表達式中使用 “\|”, 前面沒有講, 這里補上)
注:按住鍵盤的 “shift鍵” 和 “\”鍵 ,就可以打出”|”
“|”在擴展正則表達式中,表示”或”,這樣說不容易理解,我們來看個小例子,就能明白,示例文件內容如下。
如果,我們想要從上例文本中找到以”com”結尾的行,我們該怎么辦呢?我們可以使用如下命令。
同理,如果我們想要從示例文本中找出以”net”結尾的行,可以使用如下命令。
那么,如果我們想要從示例文本找出,以”com”結尾,或者以”net”結尾的行,我們該怎么辦呢?
這時候,我們就需要用到”|”
“|”在擴展正則表達式中表示”或者”,所以,我們可以使用如下表達式
上圖中的擴展正則使用了分組符號”( )”,”(com|net)”表示將括號內的內容看做一個整體,而括號內的內容為”com|net”,它表示”com或者net”,所以,”(com|net)$”就表示以com或者net結尾的行。是不是很簡單?
那么,我們就趁熱打鐵,通過實際練習,來熟悉一下”擴展正則表達式”吧。
仍然以剛才的示例文件作為測試文件,假設,我們想要查找出測試文本中的”合法郵箱”,我們應該怎么做呢?
既然是要找出”合法郵箱”,那么,我們則必須事先定義,滿足哪些條件的郵箱才屬于合法郵箱。
所以,我們規定,如果一個郵箱屬于合法郵箱,那么必須滿足如下條件。
1、郵箱字符串中必須包含”@”符。
2、”@”符前面的字符只能是小寫字母或數字,不能包含特殊符號。
3、”@”符前面的字符數量至少需要4個,至多為16個。
4、郵箱必須以”com”、”net”、”org”、”edu”等頂級域名結尾(此處為了方便演示,不判斷更多的域名)。
5、頂級域名之前必須包含一個”點”,換句話說就是,郵箱必須以”.com”、”.net”、”.org”、”.edu”結尾。
6、”@”與”.”之間的字符數量不能超過12個,不能低于2個。
7、”@”與”.”之間的字符只能是小寫字母或數字,不能包含特殊符號。
好了,了解了合法郵箱的規則以后,我們就可以開始編寫正則表達式了,我們可以使用如下正則,查找文本中的合法郵箱。
如果你覺得上述正則稍微有些復雜,不容易理解,那么可以將其拆分成幾個部分去理解,拆分后的每一部分,可以與之前的”合法郵箱條件”一一對應,如下圖所示。
這樣看,是不是容易理解多了,好了,趕快自己動手實驗一下吧。
小結
我認為,有了之前基礎的你,搞定”擴展正則表達式”,肯定是分分鐘的事情,所以,我們就對”擴展正則表達式”進行一下總結吧。
常用符號
. 表示任意單個字符。
* 表示前面的字符連續出現任意次,包括0次。
.* 表示任意長度的任意字符,與通配符中的*的意思相同。
\ 表示轉義符,當與正則表達式中的符號結合時表示符號本身。
| 表示"或者"之意
[ ]表示匹配指定范圍內的任意單個字符。
[^ ]表示匹配指定范圍外的任意單個字符。單個字符匹配相關
[[:alpha:]] 表示任意大小寫字母。
[[:lower:]] 表示任意小寫字母。
[[:upper:]] 表示任意大寫字母。
[[:digit:]] 表示0到9之間的任意單個數字(包括0和9)。
[[:alnum:]] 表示任意數字或字母。
[[:space:]] 表示任意空白字符,包括"空格"、"tab鍵"等。
[[:punct:]] 表示任意標點符號。
[^[:alpha:]] 表示單個非字母字符。
[^[:lower:]] 表示單個非小寫字母字符。
[^[:upper:]] 表示單個非大寫字母字符。
[^[:digit:]] 表示單個非數字字符。
[^[:alnum:]] 表示單個非數字非字母字符。
[^[:space:]] 表示單個非空白字符。
[^[:punct:]] 表示單個非標點符號字符。
[0-9]與[[:digit:]]等效。
[a-z]與[[:lower:]]等效。
[A-Z]與[[:upper:]]等效。
[a-zA-Z]與[[:alpha:]]等效。
[a-zA-Z0-9]與[[:alnum:]]等效。
[^0-9]與[^[:digit:]]等效。
[^a-z]與[^[:lower:]]等效。
[^A-Z]與[^[:upper:]]等效
[^a-zA-Z]與[^[:alpha:]]等效
[^a-zA-Z0-9]與[^[:alnum:]]等效次數匹配相關
? 表示匹配其前面的字符0或1次
+ 表示匹配其前面的字符至少1次,或者連續多次,連續次數上不封頂。
{n} 表示前面的字符連續出現n次,將會被匹配到。
{x,y} 表示之前的字符至少連續出現x次,最多連續出現y次,都能被匹配到,換句話說,只
要之前的字符連續出現的次數在x與y之間,即可被匹配到。
{,n} 表示之前的字符連續出現至多n次,最少0次,都會陪匹配到。
{n,}表示之前的字符連續出現至少n次,才會被匹配到。位置邊界匹配相關
^:表示錨定行首,此字符后面的任意內容必須出現在行首,才能匹配。
$:表示錨定行尾,此字符前面的任意內容必須出現在行尾,才能匹配。
^$:表示匹配空行,這里所描述的空行表示"回車",而"空格"或"tab"等都不能算作此處所描述的空行。
^abc$:表示abc獨占一行時,會被匹配到。
\<或者\b :匹配單詞邊界,表示錨定詞首,其后面的字符必須作為單詞首部出現。
\>或者\b :匹配單詞邊界,表示錨定詞尾,其前面的字符必須作為單詞尾部出現。
\B:匹配非單詞邊界,與\b正好相反。分組與后向引用
( ) 表示分組,我們可以將其中的內容當做一個整體,分組可以嵌套。
(ab) 表示將ab當做一個整體去處理。
\1 表示引用整個表達式中第1個分組中的正則匹配到的結果。
\2 表示引用整個表達式中第2個分組中的正則匹配到的結果。
那么什么時候使用基本正則表達式、什么時候使用擴展正則表達式呢?
這是一個仁者見仁的話題, 個人認為:
當出現2處或者2處以上使用“\”(反斜桿轉義)的正則, 則使用擴展正則。
基本正則表達式與擴展正則表達式的區別:
區別主要是有幾個部分可以不使用反斜桿轉義.
如下:
1. 分組;
基本正則表達式: \(\)
擴展正則表達式: ()2. 或
基本正則表達式: \|
擴展正則表達式: |3. 次數匹配相關
基本正則表達式:
\? 表示匹配其前面的字符0或1次
\+ 表示匹配其前面的字符至少1次,或者連續多次,連續次數上不封頂。
\{n\} 表示前面的字符連續出現n次,將會被匹配到。
\{x,y\} 表示之前的字符至少連續出現x次,最多連續出現y次,都能被匹配到,換句話說,只要之前的字符連續出現的次數在x與y之間,
即可被匹配到。
\{,n\} 表示之前的字符連續出現至多n次,最少0次,都會陪匹配到。
\{n,\}表示之前的字符連續出現至少n次,才會被匹配到。擴展正則表達式:
? 表示匹配其前面的字符0或1次
+ 表示匹配其前面的字符至少1次,或者連續多次,連續次數上不封頂。
{n} 表示前面的字符連續出現n次,將會被匹配到。
{x,y} 表示之前的字符至少連續出現x次,最多連續出現y次,都能被匹配到,換句話說,只
要之前的字符連續出現的次數在x與y之間,即可被匹配到。
{,n} 表示之前的字符連續出現至多n次,最少0次,都會陪匹配到。
{n,}表示之前的字符連續出現至少n次,才會被匹配到。
關于”擴展正則表達式”,就總結到這里,希望能夠幫助到你~~