正則之基本入門

之前看了許許多多的正則教程,收貨並很少,每每都是走馬觀花,一點就過。事實上,正則用處真的超級大,好比匹配innerHTML的內容,以及表單驗證,也是非他莫屬。這裏,我結合js,對正則進行一個簡單的介紹吧。 若有紕漏歡迎指出,但願你們多多包涵。html


js與正則的關係java

在js中定義一個正則有兩種方法,一個是實例化,一個是字面量。shell

分別看一下:c#

//實例化
var re = /\w+/;   //這二者等價
//字面量
var re = new RegExp('\\w+');

若是想添加一些flags也是沒有問題的。數組

比較經常使用的flag有。/i,/g,/ig,/m.markdown


/i (忽略大小寫,ignore)
/g (全文查找出現的全部匹配字符,global)
/m (多行查找,multiLine)
/ig(全文查找、忽略大小寫,ignore+global)

因此, 使用flag以後能夠這樣寫.app

var reg = ^\d{5,12}\i$  ;//表示忽略大小寫,匹配;
//或者
var reg = new RegExp(^\d{5,12}\i$);

正式入門正則
ide

正則其實就是用來匹配字符串的。他用一個簡潔表達了,完成了你須要寫不少代碼的事,就和md(markdown)語法是一個道理。 用的人多了,天然成標準,這也是規則吧。工具


正則預約字符學習

預約字符,就是用程序比較難表達的一些字符,好比回車鍵,tab鍵(經過空格來區分達到的效果).

經常使用的有:


字符 效果

\t 製表符,其實就是一個「Tab」鍵

\r 回車符,若是你使用過word應該以後,在一個段落後面那個東西吧。 :)

\n 換行符,他和\r是有故事的,等下說,咱們繼續

恩,大部分就是這幾個了。 上面提到 \r和\n,他們到底有什麼卻別。 沒錯,看字面量,感受return 不就是換行嗎? 其實,這樣說沒錯,可是得區分系統,在Unix爲擴展的系統,在每行的結尾只有"\n",而在window下則是:"\n\r"(順序不能換). 因此,爲了解決系統的差別,就出現了兩種: \r || \n.

因此通常,咱們匹配換行須要使用.\r||\n一塊兒使用.

var reg = /[\r\n]/g;

這樣就能保證系統的兼容性.


字符類

所謂的字符類一樣也是將你日常要花不少時間作出來的,集成爲一個簡潔表達。(至關於寫庫)。

經常使用的字符類有以下幾個。


字符 效果

.匹配換行符之外的任意字符
\d匹配全部數字
\D匹配非數字
\s匹配一個空格符
\S匹配非空格
\w匹配字母數字下劃線=>其實就是匹配單詞word(簡單易懂)
\W匹配!字母數字下劃線=>就是不匹配單詞

來咱們看幾個例子

console.log(/\s+/.test("     "));  //true
console.log(/\d+/.test("1234231"));  //true
console.log(/\D+/.test("  "));  //true

其餘的如上。


錨字符

這個應該算是正則裏面,取名最好理解的一個。使用正則就是停船同樣,你須要設置你停的位置,我也須要設置個人邊界。

經常使用的有一下幾個:


錨字符 效果

^匹配字符串的開頭,在多行檢索中,匹配一行的開頭
$匹配字符串的結尾,在多行檢索中,匹配一行的結尾
\b匹配一個單詞的邊界
\B匹配非單詞邊界

這幾個應該算是我日常用的最多的幾個吧。

若是你想匹配整個字符串,就能夠組合使用"^ $";


var reg = /^\d+$/; //匹配整個字符串爲數字

量詞字符

"望文生義",這類字符使用來限定某某出現的次數的。

經常使用的有:


代碼 / 語法 說明

*重複零次或更屢次
+重複一次或更屢次
?重複零次或一次
{n}重複n次
{n,}重複n次或更屢次
{n, m}重複n到m次

這個應該不用多說了。 直接看例子吧


console.log(/^\d+$/.test("123")); //true

上面說了這麼多內置的字符,那我想使用特定字符類怎麼辦嘞。其實也很簡單。使用"\"轉義字符。 

好比我想匹配大括號."{}".我能夠這樣用:


console.log(/\{.+\}/.test("{123}")); //true

但事實上,量詞還分爲3種,有貪婪量詞,惰性量詞,支配性量詞。

區分的依據是根據引擎的解析不一樣而造成。

貪婪量詞

這類量詞指的就是上文所說的: *,+,?。

他的匹配方法就是,全文匹配,若是不成功,則,將末尾的最後一個字符減去,再匹配,若是還不成功,則,再減一次。只到爲0。 接着,往中間移動一位,再進行匹配,一樣的匹配模式。


console.log(/.+/.test("abcd")); //true

惰性量詞

使用方法: 基本量詞 ?

該量詞和貪婪量詞就像,一個是消極怠工,一個是積極工做。 惰性量詞一開始只會匹配一個字符,若是不成功,則在進行匹配。


console.log(/\d+?/.test("1fjkdf")); //true

這裏闡述一些惰性和貪婪匹配的區別。

咱們也一般把惰性稱爲最少重複匹配。

舉個例子:

咱們如今須要匹配blablablabla. 中的b~a間的詞。

使用貪婪匹配:

var str = "blablablabla";
console.log(str.match(/(b.*a)/g));  //["blablablabla"]

咱們最少重複匹配(惰性匹配)

console.log(str.match(/(b.*?a)/g)); //["bla", "bla", "bla", "bla"]

支配性量詞

使用方法: 基本量詞 +; 

該量詞就是隻匹配一次,若是不符合則不匹配。

可是因爲js不支持,因此,這裏也不作過多的介紹。


正則: /\d*+/;

其實上面只要留個印象就能夠,只有當你真正使用的時候,你纔會有感觸。

OK!!!基本內容說完了,如今輪到真正的進階,big boom~


中括號的用法

咱們從小學學過來,老師告訴咱們,咱們使用括號有3種,一個是( ),一個是[],一個是{}. 

而在正則裏面,大括號已經被量詞字符給強佔了,只剩下[]和(). 這裏咱們來講一下,中括號.

[],在正則裏面表明的是一個單元字符,或者我寧願叫他"或"括號. 由於他起到的主要做用就是,你能夠匹配這個或者匹配那個或者...

吃個栗子:

var reg = /[abc]/;
console.log(reg.test("a"));  //true

能夠看出,reg能夠匹配 a|b|c. 日常使用的時候,能夠直接向一個字符使用就能夠了。

異或表達

這裏會出現一個問題,好比,我不想匹配a,b,c中的任意一個該怎麼辦呢? 其實,只須要在"[]"裏面加上"^"便可。

console.log(/[^abc]/.test("c")); //false

範圍字符

範圍字符,就是能夠省略一些周所周知的。 好比匹配26英文字母能夠直接使用:a-z. 由於咱們已經都知道了這個的意義。

其實,上面所說的字符類徹底就可使用中括號來代替。

\d => [0-9]
\w => [0-9a-zA-Z_]
\S => [^\t\n\x0B\f\r]  (\f標識分頁符)

...

另外這個範圍字符還有一個好處,就是匹配中文。(電腦都是外國人發明的呀。)

console.log(/[\u4e00-\u9fa5]{1}/.test("艹")); //true

這就是中括號的經常使用用法。


小括號使用

小括號的主要做用其實就是分組。日常是用來提取匹配到的字符串。

分組使用

使用()對內容進行區分。

console.log(/(jimmy)+/.test("jimmy")); //true

並且,配合使用match方法,能夠得到匹配到的內容.

var name = "My name is Jimmy";
console.log(name.match(/(Jimmy)/g));  //["Jimmy"]

須要注意在括號裏面寫正則和沒有括號的時候,是沒有區別的。咱們能夠在()內嵌套你想加的。(若是你想嵌套()的話,Sorry,這樣並無什麼卵用).

var name = "My name is Jimmy Jimy";
console.log(name.match(/(Jimm?y)/g));  //["Jimmy", "Jimy"]

候選(或)

這個就至關於將括號加上一個或的功能. 即,在()裏面使用"|"進行分隔。

var name = "My name is Jimmy sam";
var reg = /(jimmy|sam)+?/ig;
console.log(name.match(reg)); //["jimmy","sam"]

反向引用

這個名字我真心不理解,什麼"反向"... 我寧願叫作,給分組加上標識符。這個的主要功能,就是給匹配到的小括號加上數字,來代表他是第幾個匹配到的。若是不加,則默認從左到右的順序爲1,2,3...

var reg = /(100)\1/;
var reg2 = /(100)(99)(101)\1\2\3/; //1=>100,2=>99,3=>101

在js中,一般是和replace搭配,纔有威力。

var reg = /(100) (99)/;
var str = "100 99";
console.log(str.replace(reg,"$2 $1")); //99 100

非捕獲分組

咱們直接使用 "(...)"進行的匹配是捕獲分組。 咱們來講一下什麼叫捕獲. 上文中咱們使用match進行正則匹配,而返回的數組中的元素就是經過正則捕獲的內容。 這就叫捕獲。 

那這裏的非捕獲,是什麼意思呢? 其實很簡單,就是經過match不會匹配到內容。但仍是能夠起到分組的效果。 

格式爲: (?:xxx)

它最經常使用的地方就是匹配html.

var str=` <div class="pin">
            <div class="box">
                <img src="http://cued.xunlei.com/demos/publ/img/P_001.jpg" />
            </div>
        </div>`;
var reg = /<div(?:.|\r|\n)*div>/gi;
console.log(str.match(reg));

你們能夠去試一試,說到正則匹配,我還有一個想說的,就是上文所說的惰性匹配(最少重複)和貪婪匹配。

能夠看到 「/< div(?:.|\r|\n)*div>/gi」 我這裏使用的是貪婪匹配。他的結果是,儘可能匹配到最外層的< /div>標籤。

即上面的結果爲:

<div class="pin">
    <div class="box">
        <img src="http://cued.xunlei.com/demos/publ/img/P_001.jpg" />
    </div>
</div>

能夠看出,貪婪匹配,對於兩個重複的/div 他會匹配到最外一層。

那咱們使用惰性匹配試一試。

/< div(?:.|\r|\n)*?div>/gi

獲得的結果爲:

<div class="pin">
    <div class="box">
        <img src="http://cued.xunlei.com/demos/publ/img/P_001.jpg" />
    </div>
</div >

能夠看出少了一個< /div>,緣由就是,惰性匹配儘可能只會匹配到第一個重複的< /div>上面的。

因此,總結一下,在使用正則匹配的時候須要搞清楚到底何時用惰性,何時用貪婪,這點很重要。 貪婪會匹配最外層,惰性會匹配最裏層。


前瞻(零寬斷言)

前瞻分爲正向前瞻和反向前瞻。(因爲js只支持前瞻,因此後瞻只會提一下)。 他的做用就是,在匹配的字符後面,斷言說後面必定符合個人正則。 (好饒~~)

算了,先說一下基本格式吧。


正則 名稱 做用

(?=exp)正向前瞻匹配exp前面的位置
(?!exp)反向前瞻匹配後面不是exp的位置
(?<=exp)正向後瞻匹配exp後面的位置
(?< !exp)反向後瞻匹配後面不是exp的位置

看不懂了吧,咱們來看一下詳細的內容。

for instances:

var str = "happied boring";
var reg1 = /happ(?=ied)/g;
var reg2 = /bor(?!ied)/;
console.log(str.match(reg1)); //["happ"]
console.log(str.match(reg2)); //["bor"]

從這個例子能夠很容易看出前瞻後瞻究竟是什麼了。

回到上面的匹配html的例子。

這裏咱們有個需求,即只留下img標籤,那麼就可使用前瞻.

var str=` <div class="pin">
            <div class="box">
                <img src="http://cued.xunlei.com/demos/publ/img/P_001.jpg" />
            </div>
        </div>`;
var reg = /<(?!img)(?:.|\r|\n)*?>/gi;
console.log(str.replace(reg,""));

//獲得的結果爲:

<img src="http://cued.xunlei.com/demos/publ/img/P_001.jpg" />

另外,零寬斷言還有另一個做用,即匹配以xxx爲結尾的單詞。

這時候,你的leader對你有個要求,即,jimmy呀,你把ed結尾的單詞找出來哦。(好呀~)

這時候就可使用前瞻了。

var str = "he is an interested person";
var reg = /\b\w+(?=ed\b)/ig;
console.log(str.match(reg)); //["interest"]

結束語

關於正則的內容大概就是這些了。 其實正則的學習,不是隻用看就能學會的,實踐纔是硬道理。 經過,理論的學習,在加上踩過的坑,天然會對正則有着莫名的好感。 不過,大神就是大神,取名字就是這麼彆扭。 什麼 零寬斷言,前瞻,後瞻,反向引用 blablabla... 在理解的同時能夠根據本身的理解給這些名詞冠上本身的idea.我這裏只是 正則的冰山一角,正則在任意一門語言內,用處都是超級大的。這裏安利一個 總結的比較好的正則庫。正則庫. 還有一個在線的regExp測試工具.Debuggex

相關文章
相關標籤/搜索