何謂 Regular expression : RegExp
Regular Expressions 中文又叫做表示法,英文簡寫為 RegExp,主要功能是用來搜尋字串,分析字串,取代字串,比對字串,透過 Regular Expression,你可以用很簡單的 Pattern,來分析一篇文章。
在大部分的程式語言中,如 perl , php, shell script,都有相關 Regular Expression 的功能,學會 Regular Expression ,絕對是一個工程師必備利器,以下就開始介紹Regular Expression。
JS Regular expressions 簡易用法
先介紹幾個簡單的 Expression 用法
RegExp 在 Javascript 中有兩種方式可以定義,用來比對的描述句子我們稱之為 pattern,使用不同的 pattern 來完成字串比對,而緊接在 pattern 後面的字母,我們稱做 modifiers 修飾符號,一個完整的 Regular Expression Pattern 會像這樣「/pattern/modifiers」。
- var pattern=/test/;
- var pattern= new RegExp('test');
我們可以使用 match 這個 Method 來實作簡單的字串比較,先來試一個搜尋大小寫字母吧。
- var text="ABCDefgIJK";
- var pattern=/([A-Z]+)([a-z]+)/ ;
- text.match(pattern);
- alert(RegExp.$1 + " "+ RegExp.$2);
- // output ABCD efg
上面是一個很簡單的範例,我定義了一個字串 "ABCDefgHIJ" ,然後再定義分析的 Pattern 為 "([A-Z]+)([a-z]+)","[A-Z]" 是指比對大寫字母, "[a-z]" 則是指比對小寫字母,第一個括號(),會把比對成功的字串存到 RegExp.$1,而第二個括號會把比對成功的字串存到 RegExp.$2 。
另外 match 這個 Method 也會將比對成功的字串以 Array 的格式回傳,所以我們也可以定義一個變數去接收 match 回傳的 array ,例如 var result=text.match(/pattern/);
RegExp 相關 Method
Method | 說明 | 範例 |
---|---|---|
search | 搜尋到 Regular Expressions 符合的字串,並回傳搜尋到的字串位置 | "abc".search(/a/) |
match | 將比對成立的字串存到 Regexp ,並回傳 Array | "abc".match(/b/) |
split | 將字串切割成 Array | "a,b,c".split(/,/) |
replace | 取代字串內容 | "aabc".replace(/a+/, b) |
以上四個 Javascript 字串的 Method 都可以使用 RegExp 語法。
- //定義一個字串
- var text="A apple a day keeps the doctor away";
- //定義一個Regular Expression 比對方式
- var pattern=/(apple)/
- //搜尋字串位置
- var position=text.search(pattern);
- alert("position:"+position + " result="+text.substr(position,5));
- //Output: position:2 result=apple
- //搜尋字串內容
- var pattern=/(apple) a (day)/
- var k=text.match(pattern);
- alert("k[1]="+k[1]+" k[2]="+k[2]);
- //Output: k[1]=apple k[2]=day
- //k[0]是指比對成立的全部字串
- //以apple來分割字串
- var pattern=/apple/
- var k=text.split(pattern);
- alert("k[0]="+k[0]+" k[1]="+k[1]);
- //Output: k[0]=A k[1]= a day keeps the doctor away
- //將apple 以banana取代var pattern=/apple/
- var k=text.replace(pattern,'banana');
- alert(k);
- //Output: A banana a day keeps the doctor away
RegExp Pattern
語法 | 說明 |
---|---|
[] | 如果文字有存在 [xxx] 裡面的任一個字母,就算有符合這個規則,如 [t]: test 這個字中就有 t 這個字母,所以符合規則。 |
[a-z] |
表示有出現1個小寫字母就算是符合 , "43ar3" ,"b", "c", "f2323" 這些都符合規則,而 "323" , "$232", "-3" , 這些不符合規則 |
[0-9] |
文字只要出現 1 個數字就算是符合 |
* | 表示出現 0 次 或 多 次就算符合,如表示法 :「a*」,"aaa21" 前面三個字母符合規則 , "222abba" 只有第一個 a 符合規則 |
+ | 表示出現 1 次 或 多 次就算符合,如表示法:「a+」 , "bcdfg" 沒有出現a這個字母,所以不符合規則,"xxaaaxx" ,中間三個a符合規則 |
- var text="A apple a day keeps the doctor away";
- // keeps 這個單字連續出現兩個e,所以表示法可以寫成 k[e]*ps 或 ke{2}ps 或 ke+ps
- var pattern=/(k[e]*ps)/
- var k=text.match(pattern);
- alert(k[1]);
- //Output: keeps
- ? :表示出現 0 或 1 次,也就是說有出現就算符合,沒出現也算符合
- var text="I have apple";
- //比對不管 apple 前面有沒有出現數字都要成功,這個範例並沒有出現數字,不過是會成功的。
- var pattern=/([1-9]?apple)/
- var k=text.match(pattern);alert(k[1]);
- //Output: applevar text="I have 2 apple";
- //比對不管 apple 前面有沒有出現數字都要成功,這個例子是有出現數字的,當然也是會比對成功。
- var pattern=/([1-9]? apple)/
- var k=text.match(pattern);
- alert(k[1]);
- //Output: 2 apple
- ^ : 代表比對的開始,如 ^@([a-z]*) ,是指搜尋以@為開頭的字母
- [^] : 如果^是在[]裡面的話,代表否定的意思。如[^a-z],代表比對非a-z的字母
- //要以@開頭
- var text="@apple baanan";
- var text2="banan apple";
- var pattern=/^@([a-z]*)/
- var k=text.match(pattern);
- alert(k[1]);
- //Output: apple
- var k=text2.match(pattern);
- if(k && k[1]) alert(k[1]);
- //比對失敗:k is undefined
- $ : 代表比對的結尾,如 ([a-z]*)$ ,是指搜尋文章的最後一個單字
- \d : 代表任何一個數字,同[0-9]
- \s : 代表一個空白
- \S : 代表任何一個非空白的字串
- \w : 代表任何一個ASCII字串,同[a-zA-Z0-9_]
- \W : 代表任何一個非ASCII字串,同[^a-zA-Z0-9_]
- \D : 代表任何一個非數字字串,同[^0-9]
- {2,4} : 比對2 ~ 4 次,如 A{2.4},是指 A這個字母出現2~4次。
- {2, } : 比對2 ~ 無限次,如 A{2. },是指 A這個字母要出現2~ 無限次。
- \b : 比對一個單字的結尾。也就是說 在單字的結尾要出現一個\W的字母。
- \B : 比對一個非單字的結尾
- //使用 \b 比對apple這個單字
- var text="apple";
- var pattern=/\bapple\b/
- var k=text.match(pattern);alert(k);
- //bapple!=apple 比對失敗
- var text2="bapple";
- var k2=text2.match(pattern);
- alert(k2);
- //使用 \B apple前後要出現\w才算符合
- //比對失敗 apple前後沒有\w字元
- var text="apple";
- var pattern=/\Bapple\B/
- var k=text.match(pattern);alert(k);
- //比對成功var text2="bapple_";
- var k2=text2.match(pattern);
- alert(k2);
Ignore case 忽略大小寫
如果你要比對的資料,不想因為英文字母大小寫的不同,而比對失敗的話,就要在表示法中加上 Ignore Case ,縮寫代碼是 「i」,例如 /[a-z]/i 、 /[A-Z]/i ,這兩個表示法的結果是相同的。
Global search 全文比對
在搜尋字串時,可以一次搜尋一筆,也可以一次搜尋多筆,這時就可以利用 global 的方式,進行全文搜尋,這樣不管文章內有多少文字,只要符合表示法的規則,就會被全部抓出來,語法縮寫代碼是「g」,例如 /design/g 。
- var text="i like web design , you like web design , he likes web design";
- var regexp=/web design/g;
- var k=text.match(regexp);
- alert(k); // array(web design,web design,web design)
- //總共抓到三次的 web design
- var regexp=/web design/;
- var k=text.match(regexp);
- alert(k); //array(web design)
- //只抓到一次
多行比對
RegExp 也支援一次比對多行文字,你只要在 RegExp modifiers 中加上一個「m」,例如當你想要對一個文字檔案中,每一行的結尾加上一個分號。
- var text = "a" + "\n" + "b";
- var pattern=/([a-z])$/gm;
- text = text.replace(pattern, "$1;");
- // text =
- // a;
- // b;
簡單的範例
副檔名的判斷 Regular Expression Pattern : 「\.[^\.]{3,}$」
- {3, } 這是指前面那個東西要出現 3 次以上
- 如果我寫 a{3, } 就是說 a 要出現三次以上
- 如果我寫 b{3, } 就是說 b 要出現三次以上
- [^\.] 這個是說 出現不是 點(.) 的字
- [^\.]{3, } 合起來就是, 出現不是點(.) 的字,三次以上
- \.[^\.]{3, } 先出現一個 「. 」 , 然後再出現三個不是點的字
- a$ 代表最後一個文字「a」 之後就結束,不能再接任何文字。
- \.[^\.]{3,}$ 一個點,之後接三個不是點的字以上,然後後面不能再接任何文字。
JS RegExp 進階用法 ( Advance)
在小括號 () 裡面中,如果你使用「?」這個符號開頭,那麼 ? 是有特別含義的,Javascript Match 這個 Method 不會把符合 Regular Expression 的字串取出來。
- (?=pattern) : 比對字串,成功後,不會將 pattern 的字串取出來。
- //將 function 的名稱抓出來,比對存在括號,但是不要抓到特殊符號
- var text="apple1->test(); apple2::test();";
- var pattern=/apple[0-9](?=\:)/
- var k=text.match(pattern);
- alert(k);
- //Output: apple1
- var pattern=/apple[0-9](?=\-)/
- var k=text.match(pattern);
- alert(k);
- //Output: apple2
- (?!pattern) : 比對字串,要求不能出現 pattern,若比對符合後,不會將 pattern 的字串擷取出來。
- var text="apple1->test(); apple2::test();";
- var pattern=/[^\s]+(?!\:)/
- var k=text.match(pattern);
- alert(k);
- //Output: apple1->test();
同時比對兩個資料, RegExp的「or」 。
(?:pattern1|pattern2) : 同時比對 pattern1 與 pattern2,兩個 pattern 只要有一個符合,那麼就算是比對成功,比對到的 pattern 字串,在 Match 這個 Method 中是會被擷取出來的
另外有一個比較簡單的寫法 (pattern1|pattern2)
- //兩種function宣告方式,都會比對成功
- var text="apple1->test();
- apple2::test();";
- var pattern=/[a-z0-9]+(?:->|\:\:)/g
- var k=text.match(pattern);
- alert(k);
- //Output: apple1->,apple2::
Parse HTML table
一個 HTML 中通常會有多個 table ,而每個 table 之間又存在各種文字,這時候就要用到 non-greedy 的寫法,就是在 * (星號)後面加一個 ? ,另外用 [\s\S] 來處理多行文字。
- var html = `
- <table>
- <td>aaa</td>
- </table>
- <table>
- <td>bbb</td>
- </table>
- `;
- var reg = /<table[.\n\r\s\S]*?<\/table>/g;
- var r = html.match(reg);
- console.log(r);
- http://regexr.com/ : 這是一個 Regular expression 好用的工具。