正則學習

正則表達式是一種通用的工具,在?JavaScript、PHP、Java、PythonC++?等幾乎所有的編程語言中都能使用;但是,不同編程語言對正則表達式語法的支持不盡相同,有的編程語言支持所有的語法,有的僅支持一個子集。本節講到的正則表達式語法適用于 JavaScript。

正則表達式的語法體現在字符模式上。字符模式是一組特殊格式的字符串,它由一系列特殊字符和普通字符構成,其中每個特殊字符都包含一定的語義和功能。

描述字符

根據正則表達式語法規則,大部分字符僅能夠描述自身,這些字符被稱為普通字符,如所有的字母、數字等。

元字符就是擁有特動功能的特殊字符,大部分需要加反斜杠進行標識,以便于普通字符進行區別,而少數元字符,需要加反斜杠,以便轉譯為普通字符使用。JavaScript 正則表達式支持的元字符如表所示。

元字符

元字符描述

.查找單個字符,除了換行和行結束符

\w查找單詞字符

\W查找非單詞字符

\d查找數字

\D查找非數字字符

\s查找空白字符

\S查找非空白字符

\b匹配單詞邊界

\B匹配非單詞邊界

\0查找 NUL字符

\n查找換行符

\f查找換頁符

\r查找回車符

\t查找制表符

\v查找垂直制表符

\xxx查找以八進制數?xxxx?規定的字符

\xdd查找以十六進制數?dd?規定的字符

\uxxxx查找以十六進制?xxxx規定的 Unicode?字符

表示字符的方法有多種,除了可以直接使用字符本身外,還可以使用 ASCII?編碼或者 Unicode?編碼來表示。

示例1

下面使用 ASCII?編碼定義正則表達式直接量。

varr=/\x61/;

vars="JavaScript";

vara=s.match(s);

由于字母?a?的 ASCII?編碼為 97,被轉換為十六進制數值后為 61,因此如果要匹配字符?a,就應該在前面添加“\x”前綴,以提示它為 ASCII?編碼。

示例2

除了十六進制外,還可以直接使用八進制數值表示字符。

varr=/\141/;

vars="JavaScript";

vara=s.match(r);

使用十六進制需要添加“\x”前綴,主要是為了避免語義混淆,而八進制則不需要添加前綴。

示例3

ASCII?編碼只能夠匹配有限的單字節字符,使用 Unicode?編碼可以表示雙字節字符。Unicode?編碼方式:“\u”前綴加上 4?位十六進制值。

varr="/\u0061/";

vars="JavaScript";

vara=s.match(s);

在 RegExp()?構造函數中使用元字符時,應使用雙斜杠。

varr=newRegExp("\\u0061");

RegExp()?構造函數的參數只接受字符串,而不是字符模式。在字符串中,任何字符加反斜杠還表示字符本身,如字符串“\u”就被解釋為?u?本身,所以對于“\u0061”字符串來說,在轉換為字符模式時,就被解釋為“u0061”,而不是“\u0061”,此時反斜杠就失去轉義功能。解決方法:在字符?u?前面加雙反斜杠。

描述字符范圍

在正則表達式語法中,放括號表示字符范圍。在方括號中可以包含多個字符,表示匹配其中任意一個字符。如果多個字符的編碼順序是連續的,可以僅指定開頭和結尾字符,省略中間字符,僅使用連字符~表示。如果在方括號內添加脫字符^前綴,還可以表示范圍之外的字符。例如:

[abc]:查找方括號內任意一個字符。

[^abc]:查找不在方括號內的字符。

[0-9]:查找從 0?至 9?范圍內的數字,即查找數字。

[a-z]:查找從小寫?a?到小寫?z?范圍內的字符,即查找小寫字母。

[A-Z]:查找從大寫?A?到大寫?Z?范圍內的字符,即查找大寫字母。

[A-z]:查找從大寫?A?到小寫?z?范圍內的字符,即所有大小寫的字母。

示例1

字符范圍遵循字符編碼的順序進行匹配。如果將要匹配的字符恰好在字符編碼表中特定區域內,就可以使用這種方式表示。

如果匹配任意 ASCII?字符:

varr=/[\u0000-\u00ff]/g;

如果匹配任意雙字節的漢字:

varr=/[^\u0000-\u00ff]/g;

如果匹配任意大小寫字母和數字:

varr=/[a-zA-Z0-9]/g;

使用 Unicode?編碼設計,匹配數字:

varr=/[\u0030-\u0039]/g;

使用下面字符模式可以匹配任意大寫字母:

varr=/[\u0041-\u004A]/g;

使用下面字符模式可以匹配任意小寫字母:

varr=/[\u0061-\u007A]/g;

示例2

在字符范圍內可以混用各種字符模式。

vars="abcdez";//字符串直接量

varr=/[abce-z]/g;//字符a、b、c,以及從e~z之間的任意字符

vara=s.match(r);//返回數組["a","b","c","e","z"]

示例3

在中括號內不要有空格,否則會誤解為還要匹配空格。

varr=/[0-9]/g;

示例4

字符范圍可以組合使用,以便設計更靈活的匹配模式。

vars="abc4 abd6 abe3 abf1 abg7";//字符串直接量

varr=/ab[c-g][1-7]/g;//前兩個字符為ab,第三個字符為從c到g,第四個字符為1~7的任意數字

vara=s.match(r);//返回數組["abc4","abd6","abe3","abf1","abg7"]

示例5

使用反義字符范圍可以匹配很多無法直接描述的字符,達到以少應多的目的。

varr=/[^0123456789]/g;

在這個正則表達式中,將會匹配除了數字以外任意的字符。反義字符類比簡單字符類的功能更強大和實用。

選擇匹配

選擇匹配類似于 JavaScript?的邏輯與運算,使用豎線|描述,表示在兩個子模式的匹配結果中任選一個。例如:

1)?匹配任意數字或字母

varr=/\w+|\d+/;

2)?可以定義多重選擇模式。設計方法:在多個子模式之間加入選擇操作符。

varr=/(abc)|(efg)|(123)|(456)/;

為了避免歧義,應該為選擇操作的多個子模式加上小括號。

示例

設計對提交的表單字符串進行敏感詞過濾。先設計一個敏感詞列表,然后使用豎線把它們連接在一起,定義選擇匹配模式,最后使用字符串的?replace()?方法把所有敏感字符替換為可以顯示的編碼格式。代碼如下:

vars='<meta charset="utf-8">';//待過濾的表單提交信息

varr=/\'|\"|\<|\>/gi;//過濾敏感字符的正則表達式

functionf(){//替換函數

////把敏感字符替換為對應的網頁顯示的編碼格式

return"&#"+arguments[0].charCodeAt(0)+";";

}

vara=s.replace(r,f);//執行過濾替換

document.write(a);//在網頁中顯示正常的字符信息

console.log(a);

顯示結果如下:

重復匹配

在正則表達式語法中,定義了一組重復類量詞,如表所示。它們定義了重復匹配字符的確數或約數。

重復類量詞列表

量詞描述

n+匹配任何包含至少一個?n?的字符串

n*匹配任何包含零個或多個?n?的字符串

n?匹配任何包含零個或一個?n?的字符串

n{x}匹配包含?x?個?n?的序列的字符串

n{x,y}匹配包含最少?x?個、最多?y?個?n?的序列的字符串

n{x,}匹配包含至少?x?個?n?的序列的字符串

示例

下面結合示例進行演示說明,先設計一個字符串:

vars="ggle gogle google gooogle goooogle gooooogle goooooogle gooooooogle goooooooogle";

1)?如果僅匹配單詞?ggle?和?gogle,可以設計:

varr=/go?gle/g;

vara=s.match(r);

量詞?表示前面字符或子表達式為可有可無,等效于:

varr=/go{0,1}gle/g;

vara=s.match(r);

2)?如果匹配第 4?個單詞?gooogle,可以設計:

varr=/go{3}gle/g;

vara=s.match(r);

等效于:

varr=/gooogle/g;

vara=s.match(r);

3)?如果匹配第 4?個到第 6?個之間的單詞,可以設計:

varr=/go{3,5}gle/g;

vara=s.match(r);

4)?如果匹配所有單詞,可以設計:

varr=/go*gle/g;

vara=s.match(r);

量詞*表示前面字符或表達式可以不出現,或者重復出現任意多次。等效于:

varr=/go(0,)gle/g;

vara=s.match(r);

5)?如果匹配包含字符“o”的所有詞,可以設計:

varr=/go+gle/g;

vara=s.match(r);

量詞+表示前面字符或子表達式至少出現 1?次,最多重復次數不限。等效于:

varr=/go{1,}gle/g;

vara=s.match(r);

重復類量詞總是出現在它們所作用的字符或子表達式后面。如果想作用于多個字符,需要使用小括號把它們包裹在一起形成一個子表達式。

惰性匹配

重復類量詞都具有貪婪性,在條件允許的前提下,會匹配盡可能多的字符。

?、{n} 和 {n,m}?重復類具有弱貪婪性,表現為貪婪的有限性。

*、+?和 {n,}?重復類具有強貪婪性,表現為貪婪的無限性。

示例1

越是排在左側的重復類量詞匹配優先級越高。下面示例顯示當多個重復類量詞同時滿足條件時,會在保證右側重復類量詞最低匹配次數基礎上,使最左側的重復類量詞盡可能占有所有字符。

vars="<html><head><title></title></head><body></body></html>";

varr=/(<.*>)(<.*>)/

vara=s.match(r);

//左側表達式匹配"<html><head><title></title></head><body></body></html>"

console.log(a[1]);

console.log(a[2]);//右側表達式匹配“</html>”

與貪婪匹配相反,惰性匹配將遵循另一種算法:在滿足條件的前提下,盡可能少的匹配字符。定義惰性匹配的方法:在重復類量詞后面添加問號?限制詞。貪婪匹配體現了最大化匹配原則,惰性匹配則體現最小化匹配原則。

示例2

下面示例演示了如何定義匹配模式。

vars="<html><head><title></title></head><body></body></html>";

varr=/<.*?>/

vara=s.match(r);//返回單個元素數組["<html>"]

在上面示例中,對于正則表達式 /<.*?>/?來說,它可以返回匹配字符串 "<>",但是為了能夠確保匹配條件成立,在執行中還是匹配了帶有 4?個字符的字符串“html”。惰性取值不能夠以違反模式限定的條件而返回,除非沒有找到符合條件的字符串,否則必須滿足它。

針對 6?種重復類惰性匹配的簡單描述如下:

{n,m}?:盡量匹配?n?次,但是為了滿足限定條件也可能最多重復?m?次。

{n}?:盡量匹配?n?次。

{n,}?:盡量匹配?n?次,但是為了滿足限定條件也可能匹配任意次。

??:盡量匹配,但是為了滿足限定條件也可能最多匹配 1?次,相當于 {0,1}?。

+?:盡量匹配 1?次,但是為了滿足限定條件也可能匹配任意次,相當于 {1,}?。

*? :盡量不匹配,但是為了滿足限定條件也可能匹配任意次,相當于 {0,}?。

邊界量詞

邊界就是確定匹配模式的位置,如字符串的頭部或尾部,具體說明如表所示。

JavaScript 正則表達式支持的邊界量詞

量詞說明

^匹配開頭,在多行檢測中,會匹配一行的開頭

$匹配結尾,在多行檢測中,會匹配一行的結尾

下面代碼演示如何使用邊界量詞。先定義字符串:

vars="how are you"

1)?匹配最后一個單詞

varr=/\w+$/;

vara=s.match(r);//返回數組["you"]

2)?匹配第一個單詞

varr=/^\w+/;

vara=s.match(r);//返回數組["how"]

3)?匹配每一個單詞

varr=/\w+/g;

vara=s.match(r);//返回數組["how","are","you"]

聲明詞量

聲明表示條件的意思。聲明詞量包括正向聲明和反向聲明兩種模式。

正向聲明

指定匹配模式后面的字符必須被匹配,但又不返回這些字符。語法格式如下:

匹配模式 (?=?匹配條件)

聲明包含在小括號內,它不是分組,因此作為子表達式。

下面代碼定義一個正前向生命的匹配模式。

vars="one : 1; two : 2";

varr=/\w*(?==)/;//使用正前向聲明,指定執行匹配必須滿足的條件

vara=s.match(r);//返回數組["two"]

在上面示例中,通過?==錨定條件,指定只有在 \w* 所能夠匹配的字符后面跟隨一個等號字符,才能夠執行 \w*?匹配。所以,最后匹配的字符串“two”,而不是字符串“one”。

反向聲明

與正向聲明匹配相反,指定接下來的字符都不必被匹配。語法格式如下:

匹配模式(?!?匹配條件)

下面代碼定義一個反前向生命的匹配模式。

vars="one : 1; two : 2";

varr=/\w*(?!=)/;//使用正前向聲明,指定執行匹配不必滿足的條件

vara=s.match(r);//返回數組["one"]

在上面示例中,通過?!=錨定條件,指定只有在“\w*”所能夠匹配的字符后面不跟隨一個等號字符,才能夠執行 \w*匹配。所以,最后匹配的是字符串“one”,而不是字符串“two”。

子表達式

使用小括號可以對字符模式進行任意分組,在小括號內的字符串表示子表達式,也稱為子模式。子表達式具有獨立的匹配功能,保存獨立的匹配結果;同時,小括號后的量詞將會作用于整個子表達式。

通過分組可以在一個完整的字符模式中定義一個或多個子模式。當正則表達式成功地匹配目標字符串后,也可以從目標字符串中抽出與子模式相匹配的子內容。

示例

在下面代碼中,不僅能匹配出每個變量聲明,同時還抽出每個變量及其值。

vars="ab=21, bc=45, cd=43";

varr=/(\w+)=(\d*)/g;

while(a=r.exec(s)){

console.log(a);//返回類似["ab=21","bc=45","cd=43"]三個數組

}

反向引用

在字符模式中,后面的字符可以引用前面的子表達式。實現方法如下:

\+?數字

數字指定了子表達式在字符模式中的順序。如“\1”引用的是第 1?個子表達式,“\2”引用的是第 2?個子表達式。

示例1

在下面代碼中,通過引用前面子表達式匹配的文本,實現成組匹配字符串。

vars="<h1>title<h1><p>text<p>";

varr=/(<\/?\w+>)\1/g;

vara=s.match(r);//返回數組["<h1>title<h1>","<p>text<p>"]

由于子表達式可以相互嵌套,它們的順序將根據左括號的順序來確定。例如,下面示例定義匹配模式包含多個子表達式。

vars="abc";

varr=/(a(b(c)))/;

vara=s.match(r);//返回數組["abc","abc","bc","c"]

在這個模式中,共產生了 3?個反向引用,第一個是“(a(b(c)))”,第二個是“(b(c))”,第三個是“(C)”。它們引用的匹配文本分別是字符串“abc”、“bc”和“c”。

對子表達式的引用,是指引用前面子表達式所匹配的文本,而不是子表達式的匹配模式。如果要引用前面子表達式的匹配模式,則必須使用下面方式,只有這樣才能夠達到匹配目的。

vars="<h1>title</h1><p>text</p>";

varr=/((<\/?\w+>).*(<\/?\w+>))/g;

vara=s.match(r);//返回數組["<h1>title</h1>","<p>text</p>"]

反向引用在開發中主要有以下幾種常規用法。

示例2

在正則表達式對象的?test()?方法中,以及字符串對象的?match()?和?search()?等方法中使用。在這些方法中,反向引用的值可以從 RegExp()?構造函數中獲得。

vars="abcdefghijklmn";

varr=/(\w)(\w)(\w)/;

r.test(s);

console.log(RegExp.$1);//返回第1個子表達式匹配的字符a

console.log(RegExp.$2);//返回第2個子表達式匹配的字符b

console.log(RegExp.$3);//返回第3個子表達式匹配的字符c

????通過上面示例可以看到,正則表達式執行匹配檢測后,所有子表達式匹配的文本都被分組存儲在 RegExp()?構造函數的屬性內,通過前綴符號$與正則表達式中子表達式的編號來引用這些臨時屬性。其中屬性 $1?標識符指向第 1?個值引用,屬性 $2?標識符指向第 2?個值引用。

示例3

可以直接在定義的字符模式中包含反向引用。這可以通過使用特殊轉義序列(如 \1、\2 等)來實現。

vars="abcbcacba";

varr=/(\w)(\w)(\w)\2\3\1\3\2\1/;

varb=r.test(s);//驗證正則表達式是否匹配該字符串

console.log(b);//返回true

在上面示例的正則表達式中,“\1”表示對第 1?個反向引用 (\w)?所匹配的字符?a?進行引用,“\2”表示對第 2?個反向引用 (\w)?所匹配的字符串?b?進行引用,“\3”表示對第 3?個反向引用 (\w)?所匹配的字符?c?進行引用。

示例4

可以在字符串對象的?replace()?方法中使用。通過使用特殊字符序列$1、$2、$3?等來實現。例如,在下面的示例中將顛倒相鄰字母和數字的位置。

vars="aa11bb22c3d4e5f6";

varr=/(\w+?)(\d+)/g;

varb=s.replace(r,"$2$1");

console.log(b);//返回字符串“aa11bb22c3? d4e5f6”

在上面例子中,正則表達式包括兩個分組,第 1?個分組匹配任意連續的字母,第 2?個分組匹配任意連續的數字。在?replace()?方法的第 2?個參數中,$1?表示對正則表達式中第 1?個子表達式匹配文本的引用,而 $2?表示對正則表達式中第 2?個子表達式匹配文本的引用,通過顛倒 $1?和 $2?標識符的位置,即可實現字符串的顛倒來替換原字符串。

禁止引用

反向引用會占用一定的系統資源,在較長的正則表達式中,反向引用會降低匹配速度。如果分組僅僅是為了方便操作,可以禁止反向引用。

實現方法:在左括號的后面加上一個問號和冒號。

vars1="abc";

varr=/(?:\w*?)|(?:\d*?)/;

vara=r.test(si);

非引用型分組必須使用子表達式,但是又不希望存儲無用的匹配信息,或者希望提高匹配速度來說,是非常重用的方法。

案例引用自:JS正則表達式語法大全(非常詳細) (biancheng.net)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容

  • 前端時間的自學的時候,怎么沒吃透正則的用法,最近js有一定的提高,開始有時間補充漏洞的時候! 1.何為正則呢? 正...
    love2013閱讀 295評論 0 1
  • 一、常用的匹配規則總結表 原文鏈接 相關具體應用例子,請見:Python-正則表達式 二、re庫中常用方法 相關具...
    夜空最亮的9星閱讀 342評論 0 3
  • 一種特征 / pattern / flag 兩種形式 構造函數方式var reg = new RegExp('\d...
    jackie_su閱讀 223評論 0 0
  • 速記: [ ] [ - ]中括號表示其中一個字符作為結果 [^ ]中括號里面加入 ^ 表示非的意思,不包括里面的字...
    iOS打怪升級閱讀 271評論 0 0
  • 題注:正則表達式也稱為規則表達式或字符串規則表達式,此文記錄正則表達式的一些基本用法,適合正則入門使用。 基本規則...
    shaipxiang閱讀 391評論 0 0