正則表達式

1、簡介

  正則表達式,又稱規則表達式,英文名爲Regular Expression,在代碼中常簡寫爲regex、regexp或RE,是計算機科學的一個概念。正則表一般被用來檢索、替換那些符合某個模式(規則)的文本。
  正則表達式是對字符串(包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱爲「元字符」))操做的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。正則表達式是一種文本模式,模式描述在搜索文本時要匹配的一個或多個字符串。

2、概念

  正則表達式是對 字符串操做的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。
給定一個正則表達式和另外一個字符串,咱們能夠達到以下的目的:
1. 給定的字符串是否符合正則表達式的過濾邏輯(稱做「匹配」);
2. 能夠經過正則表達式,從字符串中獲取咱們想要的特定部分。
正則表達式的特色是:
1. 靈活性、邏輯性和功能性很是強;
2. 能夠迅速地用極簡單的方式達到字符串的複雜控制。
3. 對於剛接觸的人來講,比較晦澀難懂。
因爲正則表達式主要 應用對象是文本,所以它在各類 文本編輯器場合都有應用,小到著名編輯器EditPlus,大到Microsoft Word、Visual Studio等大型編輯器,均可以使用正則表達式來處理文本內容。

3、符號

(摘自《 正則表達式之道》)
正則表達式[2]   由一些普通 字符和一些 元字符(metacharacters)組成。普通字符包括大小寫的字母和數字,而元字符則具備特殊的含義,咱們下面會給予解釋。
在最簡單的狀況下,一個正則表達式看上去就是一個普通的查找串。例如,正則表達式"testing"中沒有包含任何元字符,它能夠匹配"testing"和"testing123"等字符串,可是不能匹配"Testing"。
要想真正的用好正則表達式,正確的理解元字符是最重要的事情。下表列出了全部的元字符和對它們的一個簡短的描述。
 
元字符
描述
\
將下一個字符標記符、或一個向後引用、或一個八進制轉義符。例如,「\\n」匹配\n。「\n」匹配換行符。序列「\\」匹配「\」而「\(」則匹配「(」。即至關於多種編程語言中都有的「轉義字符」的概念。
^
匹配輸入字行首。若是設置了RegExp對象的Multiline屬性,^也匹配「\n」或「\r」以後的位置。
$
匹配輸入行尾。若是設置了RegExp對象的Multiline屬性,$也匹配「\n」或「\r」以前的位置。
*
匹配前面的子表達式任意次。例如,zo*能匹配「z」,也能匹配「zo」以及「zoo」。*等價於o{0,}
+
匹配前面的子表達式一次或屢次(大於等於1次)。例如,「zo+」能匹配「zo」以及「zoo」,但不能匹配「z」。+等價於{1,}。
?
匹配前面的子表達式零次或一次。例如,「do(es)?」能夠匹配「do」或「does」中的「do」。?等價於{0,1}。
{n}
n是一個非負整數。匹配肯定的n次。例如,「o{2}」不能匹配「Bob」中的「o」,可是能匹配「food」中的兩個o。
{n,}
n是一個非負整數。至少匹配n次。例如,「o{2,}」不能匹配「Bob」中的「o」,但能匹配「foooood」中的全部o。「o{1,}」等價於「o+」。「o{0,}」則等價於「o*」。
{n,m}
m和n均爲非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,「o{1,3}」將匹配「fooooood」中的前三個o爲一組,後三個o爲一組。「o{0,1}」等價於「o?」。請注意在逗號和兩個數之間不能有空格。
?
當該字符緊跟在任何一個其餘限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串「oooo」,「o+」將盡量多的匹配「o」,獲得結果[「oooo」],而「o+?」將盡量少的匹配「o」,獲得結果 ['o', 'o', 'o', 'o']
.點
匹配除「\r\n」以外的任何單個字符。要匹配包括「\r\n」在內的任何字符,請使用像「[\s\S]」的模式。
(pattern)
匹配pattern並獲取這一匹配。所獲取的匹配能夠從產生的Matches集合獲得,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字符,請使用「\(」或「\)」。
(?:pattern)
非獲取匹配,匹配pattern但不獲取匹配結果,不進行存儲供之後使用。這在使用或字符「(|)」來組合一個模式的各個部分時頗有用。例如「industr(?:y|ies)」就是一個比「industry|industries」更簡略的表達式。
(?=pattern)
非獲取匹配,正向確定預查,在任何匹配pattern的字符串開始處匹配查找字符串,該匹配不須要獲取供之後使用。例如,「Windows(?=95|98|NT|2000)」能匹配「Windows2000」中的「Windows」,但不能匹配「Windows3.1」中的「Windows」。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。
(?!pattern)
非獲取匹配,正向否認預查,在任何不匹配pattern的字符串開始處匹配查找字符串,該匹配不須要獲取供之後使用。例如「Windows(?!95|98|NT|2000)」能匹配「Windows3.1」中的「Windows」,但不能匹配「Windows2000」中的「Windows」。
(?<=pattern)
非獲取匹配,反向確定預查,與正向確定預查相似,只是方向相反。例如,「(?<=95|98|NT|2000)Windows」能匹配「2000Windows」中的「Windows」,但不能匹配「3.1Windows」中的「Windows」。
(?<!pattern)
非獲取匹配,反向否認預查,與正向否認預查相似,只是方向相反。例如「(?<!95|98|NT|2000)Windows」能匹配「3.1Windows」中的「Windows」,但不能匹配「2000Windows」中的「Windows」。這個地方不正確,有問題
此處用或任意一項都不能超過2位,如「(?<!95|98|NT|20)Windows正確,「(?<!95|980|NT|20)Windows 報錯,如果單獨使用則無限制,如(?<!2000)Windows 正確匹配
x|y
匹配x或y。例如,「z|food」能匹配「z」或「food」(此處請謹慎)。「[zf]ood」則匹配「zood」或「food」。
[xyz]
字符集合。匹配所包含的任意一個字符。例如,「[abc]」能夠匹配「plain」中的「a」。
[^xyz]
負值字符集合。匹配未包含的任意字符。例如,「[^abc]」能夠匹配「plain」中的「plin」。
[a-z]
字符範圍。匹配指定範圍內的任意字符。例如,「[a-z]」能夠匹配「a」到「z」範圍內的任意小寫字母字符。
注意:只有連字符在字符組內部時,而且出如今兩個字符之間時,才能表示字符的範圍; 若是出字符組的開頭,則只能表示連字符自己.
[^a-z]
負值字符範圍。匹配任何不在指定範圍內的任意字符。例如,「[^a-z]」能夠匹配任何不在「a」到「z」範圍內的任意字符。
\b
匹配一個單詞邊界,也就是指單詞和空格間的位置(即正則表達式的「匹配」有兩種概念,一種是匹配字符,一種是匹配位置,這裏的\b就是匹配位置的)。例如,「er\b」能夠匹配「never」中的「er」,但不能匹配「verb」中的「er」。
\B
匹配非單詞邊界。「er\B」能匹配「verb」中的「er」,但不能匹配「never」中的「er」。
\cx
匹配由x指明的控制字符。例如,\cM匹配一個Control-M或回車符。x的值必須爲A-Z或a-z之一。不然,將c視爲一個原義的「c」字符。
\d
匹配一個數字字符。等價於[0-9]。grep 要加上-P,perl正則支持
\D
匹配一個非數字字符。等價於[^0-9]。grep要加上-P,perl正則支持
\f
匹配一個換頁符。等價於\x0c和\cL。
\n
匹配一個換行符。等價於\x0a和\cJ。
\r
匹配一個回車符。等價於\x0d和\cM。
\s
匹配任何不可見字符,包括空格、製表符、換頁符等等。等價於[ \f\n\r\t\v]。
\S
匹配任何可見字符。等價於[^ \f\n\r\t\v]。
\t
匹配一個製表符。等價於\x09和\cI。
\v
匹配一個垂直製表符。等價於\x0b和\cK。
\w
匹配包括下劃線的任何單詞字符。相似但不等價於「[A-Za-z0-9_]」,這裏的"單詞"字符使用Unicode字符集。
\W
匹配任何非單詞字符。等價於「[^A-Za-z0-9_]」。
\xn
匹配n,其中n爲十六進制轉義值。十六進制轉義值必須爲肯定的兩個數字長。例如,「\x41」匹配「A」。「\x041」則等價於「\x04&1」。正則表達式中可使用ASCII編碼。
\num
匹配num,其中num是一個正整數。對所獲取的匹配的引用。例如,「(.)\1」匹配兩個連續的相同字符。
\n
標識一個八進制轉義值或一個向後引用。若是\n以前至少n個獲取的子表達式,則n爲向後引用。不然,若是n爲八進制數字(0-7),則n爲一個八進制轉義值。
\nm
標識一個八進制轉義值或一個向後引用。若是\nm以前至少有nm個得到子表達式,則nm爲向後引用。若是\nm以前至少有n個獲取,則n爲一個後跟文字m的向後引用。若是前面的條件都不知足,若n和m均爲八進制數字(0-7),則\nm將匹配八進制轉義值nm。
\nml
若是n爲八進制數字(0-7),且m和l均爲八進制數字(0-7),則匹配八進制轉義值nml。
\un
匹配n,其中n是一個用四個十六進制數字表示的Unicode字符。例如,\u00A9匹配版權符號(&copy;)。
\p{P}
小寫 p 是 property 的意思,表示 Unicode 屬性,用於 Unicode 正表達式的前綴。中括號內的「P」表示Unicode 字符集七個字符屬性之一:標點字符。
其餘六個屬性:
L:字母;
M:標記符號(通常不會單獨出現);
Z:分隔符(好比空格、換行等);
S:符號(好比數學符號、貨幣符號等);
N:數字(好比阿拉伯數字、羅馬數字等);
C:其餘字符。
*注:此語法部分語言不支持,例:javascript。
\<
\>
匹配詞(word)的開始(\<)和結束(\>)。例如正則表達式\<the\>可以匹配字符串"for the wise"中的"the",可是不能匹配字符串"otherwise"中的"the"。注意:這個元字符不是全部的軟件都支持的。
( ) 將( 和 ) 之間的表達式定義爲「組」(group),而且將匹配這個表達式的字符保存到一個臨時區域(一個正則表達式中最多能夠保存9個),它們能夠用 \1 到\9 的符號來引用。
| 將兩個匹配條件進行邏輯「或」(Or)運算。例如正則表達式(him|her) 匹配"it belongs to him"和"it belongs to her",可是不能匹配"it belongs to them."。注意:這個元字符不是全部的軟件都支持的。
 
最簡單的 元字符是點,它可以匹配任何單個字符(注意不包括換行符)。假定有個文件test.txt包含如下幾行內容:
he is arat
he is in a rut
the food is Rotten
I like root beer
咱們可使用grep命令來測試咱們的正則表達式,grep命令 使用正則表達式去嘗試匹配指定文件的每一行,並將至少有一處匹配表達式的全部行顯示出來。命令
grep r.t test.txt
在test.txt文件中的每一行中搜索正則表達式r.t,並打印輸出匹配的行。正則表達式r.t匹配一個r接着任何一個字符再接着一個t。因此它將匹配文件中的rat和rut,而不能匹配Rotten中的Rot,由於正則表達式是大小寫敏感的。要想同時匹配大寫和小寫字母,應該使用 字符區間 元字符(方括號)。正則表達式[Rr]可以同時匹配R和r。因此,要想匹配一個大寫或者小寫的r接着任何一個字符再接着一個t就要使用這個表達式:[Rr].t。
要想匹配行首的字符要使用抑揚字符(^)——有時也被叫作插入符。例如,想找到text.txt中行首"he"打頭的行,你可能會先用簡單表達式he,可是這會匹配第三行的the,因此要 使用正則表達式^he,它只匹配在行首出現的he。
有時候指定「除了×××都匹配」會比較容易達到目的,當抑揚字符(^)出方括號中時,它表示「排除」,例如要匹配he ,可是排除前面是t or s的情形(也就是the和she),可使用:[^st]he。
可使用方括號來指定多個字符區間。例如正則表達式[A-Za-z]匹配任何字母,包括大寫和小寫的;正則表達式[A-Za-z][A-Za-z]* 匹配一個字母后面接着0或者多個字母(大寫或者小寫)。固然咱們也能夠用 元字符+作到一樣的事情,也就是:[A-Za-z]+ ,和[A-Za-z][A-Za-z]*徹底等價。可是要注意元字符+ 並非全部支持正則表達式的程序都支持的。關於這一點能夠參考後面的正則表達式語法支持狀況。
要指定特定數量的匹配,要使用大括號(注意必須使用 反斜槓來轉義)。想匹配全部10和100的實例而排除1和 1000,可使用:10\{1,2\},這個正則表達式匹配數字1後面跟着1或者2個0的模式。在這個元字符的使用中一個有用的變化是忽略第二個數字,例如正則表達式0\{3,\} 將匹配至少3個連續的0。
例1
將全部方法foo(a,b,c)的實例改成foo(b,a,c)。這裏a、b和c能夠是任何提供給方法foo()的參數。也就是說咱們要實現這樣的轉換:
以前 以後
foo(10,7,2) foo(7,10,2)
foo(x+13,y-2,10) foo(y-2,x+13,10)
foo( bar(8), x+y+z, 5) foo( x+y+z, bar(8), 5)
下面這條替換命令可以實現這一方法:
:%s/foo(\([^,]*\),\([^,]*\),\([^,)]*\))/foo(\2,\1,\3)/g
讓咱們把它打散來加以分析。寫出這個表達式的基本思路是找出foo()和它的括號中的三個參數的位置。第一個參數是用這個表達式來識別的::\([^,]*\),咱們能夠從裏向外來分析它:
[^,] 除了逗號以外的任何字符
[^,]* 0或者多個非逗號字符
\([^,]*\) 將這些非逗號字符標記爲\1,這樣能夠在以後的替換模式表達式中引用它
\([^,]*\), 咱們必須找到0或者多個非逗號 字符後面跟着一個逗號,而且非逗號字符那部分要標記出來以備後用。
正是指出一個 使用正則表達式常見錯誤的最佳時機。爲何咱們要使用[^,]*這樣的一個表達式,而不是更加簡單直接的寫法,例如:.*,來匹配第一個參數呢?設想咱們使用模式.*來匹配字符串"10,7,2",它應該匹配"10,"仍是"10,7,"?爲了解決這個兩義性(ambiguity),正則表達式規定一概按照最長的串來,在上面的例子中就是"10,7,",顯然這樣就找出了兩個參數而不是咱們指望的一個。因此,咱們要使用[^,]*來強制取出第一個逗號以前的部分。
這個表達式咱們已經分析到了:foo(\([^,]*\),這一段能夠簡單的翻譯爲「當你找到foo(就把其後直到第一個逗號以前的部分標記爲\1」。而後咱們使用一樣的辦法標記第二個參數爲\2。對第三個參數的標記方法也是同樣,只是咱們要搜索全部的字符直到右括號。咱們並無必要去搜索第三個參數,由於咱們不須要調整它的位置,可是這樣的模式可以保證咱們只去替換那些有三個參數的foo()方法調用,在foo()是一個 重載(overloading)方法時這種明確的模式每每是比較保險的。而後,在替換部分,咱們找到foo()的對應實例,而後利用標記好的部分進行替換,是把第一和第二個參數交換位置。

4、詳細連接

寫在博客裏只是爲了之後參考方便,詳細知識來源:https://baike.baidu.com/item/正則表達式/1700215?fr=aladdinjavascript

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息