2011
Sep
03

網頁好讀版

何謂 Regular expression : RegExp

Regular Expressions 中文又叫做表示法,英文簡寫為 RegExp,主要功能是用來搜尋字串,分析字串,取代字串,比對字串,透過 Regular Expression,你可以用很簡單的 Pattern,來分析一篇文章。

在大部分的程式語言中,如 perl , php, shell script,都有相關 Regular Expression 的功能,學會 Regular Expression ,絕對是一個工程師必備利器,以下就開始介紹Regular Expression。

JS Regular expressions 簡易用法

先介紹幾個簡單的 Expression 用法

如果已經有基礎的同學,就直接往下看 Advance 吧。

RegExp 在 Javascript 中有兩種方式可以定義,用來比對的描述句子我們稱之為 pattern,使用不同的 pattern 來完成字串比對,而緊接在 pattern 後面的字母,我們稱做 modifiers 修飾符號,一個完整的 Regular Expression Pattern 會像這樣「/pattern/modifiers」。

定義 Regular Expression
  1. var pattern=/test/;
  2. var pattern= new RegExp('test');


我們可以使用 match 這個 Method 來實作簡單的字串比較,先來試一個搜尋大小寫字母吧。

Example
  1. var text="ABCDefgIJK";
  2. var pattern=/([A-Z]+)([a-z]+)/ ;
  3. text.match(pattern);
  4. alert(RegExp.$1 + " "+ RegExp.$2);
  5. // 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 語法。

Example
  1. //定義一個字串
  2. var text="A apple a day keeps the doctor away";
  3. //定義一個Regular Expression 比對方式
  4. var pattern=/(apple)/
  5. //搜尋字串位置
  6. var position=text.search(pattern);
  7. alert("position:"+position + " result="+text.substr(position,5));
  8. //Output: position:2 result=apple
  9.  
  10. //搜尋字串內容
  11. var pattern=/(apple) a (day)/
  12. var k=text.match(pattern);
  13. alert("k[1]="+k[1]+" k[2]="+k[2]);
  14. //Output: k[1]=apple k[2]=day
  15.  
  16.  
  17. //k[0]是指比對成立的全部字串
  18. //以apple來分割字串
  19. var pattern=/apple/
  20. var k=text.split(pattern);
  21. alert("k[0]="+k[0]+" k[1]="+k[1]);
  22. //Output: k[0]=A k[1]= a day keeps the doctor away
  23.  
  24.  
  25. //將apple 以banana取代var pattern=/apple/
  26. var k=text.replace(pattern,'banana');
  27. alert(k);
  28. //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符合規則
Example
  1. var text="A apple a day keeps the doctor away";
  2. // keeps 這個單字連續出現兩個e,所以表示法可以寫成 k[e]*ps 或 ke{2}ps 或 ke+ps
  3. var pattern=/(k[e]*ps)/
  4. var k=text.match(pattern);
  5. alert(k[1]);
  6. //Output: keeps
  • ? :表示出現 0 或 1 次,也就是說有出現就算符合,沒出現也算符合
Example
  1. var text="I have apple";
  2. //比對不管 apple 前面有沒有出現數字都要成功,這個範例並沒有出現數字,不過是會成功的。
  3. var pattern=/([1-9]?apple)/
  4. var k=text.match(pattern);alert(k[1]);
  5. //Output: applevar text="I have 2 apple";
  6. //比對不管 apple 前面有沒有出現數字都要成功,這個例子是有出現數字的,當然也是會比對成功。
  7. var pattern=/([1-9]? apple)/
  8. var k=text.match(pattern);
  9. alert(k[1]);
  10. //Output: 2 apple
  • ^ : 代表比對的開始,如 ^@([a-z]*) ,是指搜尋以@為開頭的字母
  • [^] : 如果^是在[]裡面的話,代表否定的意思。如[^a-z],代表比對非a-z的字母
Example
  1. //要以@開頭
  2. var text="@apple baanan";
  3. var text2="banan apple";
  4. var pattern=/^@([a-z]*)/
  5. var k=text.match(pattern);
  6. alert(k[1]);
  7. //Output: apple
  8. var k=text2.match(pattern);
  9. if(k && k[1]) alert(k[1]);
  10. //比對失敗: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 : 比對一個非單字的結尾
Example
  1. //使用 \b 比對apple這個單字
  2. var text="apple";
  3. var pattern=/\bapple\b/
  4. var k=text.match(pattern);alert(k);
  5. //bapple!=apple 比對失敗
  6. var text2="bapple";
  7. var k2=text2.match(pattern);
  8. alert(k2);
  9. //使用 \B apple前後要出現\w才算符合
  10. //比對失敗 apple前後沒有\w字元
  11. var text="apple";
  12. var pattern=/\Bapple\B/
  13. var k=text.match(pattern);alert(k);
  14. //比對成功var text2="bapple_";
  15. var k2=text2.match(pattern);
  16. alert(k2);

Ignore case 忽略大小寫

如果你要比對的資料,不想因為英文字母大小寫的不同,而比對失敗的話,就要在表示法中加上 Ignore Case ,縮寫代碼是 「i」,例如 /[a-z]/i 、 /[A-Z]/i ,這兩個表示法的結果是相同的。

Global search 全文比對

在搜尋字串時,可以一次搜尋一筆,也可以一次搜尋多筆,這時就可以利用 global 的方式,進行全文搜尋,這樣不管文章內有多少文字,只要符合表示法的規則,就會被全部抓出來,語法縮寫代碼是「g」,例如 /design/g 。

Example
  1. var text="i like web design , you like web design , he likes web design";
  2. var regexp=/web design/g;
  3. var k=text.match(regexp);
  4. alert(k); // array(web design,web design,web design)
  5. //總共抓到三次的 web design
  6.  
  7. var regexp=/web design/;
  8. var k=text.match(regexp);
  9. alert(k); //array(web design)
  10. //只抓到一次

多行比對

RegExp 也支援一次比對多行文字,你只要在 RegExp modifiers 中加上一個「m」,例如當你想要對一個文字檔案中,每一行的結尾加上一個分號。

Example
  1. var text = "a" + "\n" + "b";
  2.  
  3. var pattern=/([a-z])$/gm;
  4. text = text.replace(pattern, "$1;");
  5. // text =
  6. // a;
  7. // 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 的字串取出來。
Example
  1. //將 function 的名稱抓出來,比對存在括號,但是不要抓到特殊符號
  2. var text="apple1->test(); apple2::test();";
  3. var pattern=/apple[0-9](?=\:)/
  4. var k=text.match(pattern);
  5. alert(k);
  6. //Output: apple1
  7.  
  8. var pattern=/apple[0-9](?=\-)/
  9. var k=text.match(pattern);
  10. alert(k);
  11. //Output: apple2
  • (?!pattern) : 比對字串,要求不能出現 pattern,若比對符合後,不會將 pattern 的字串擷取出來。
Example
  1. var text="apple1->test(); apple2::test();";
  2. var pattern=/[^\s]+(?!\:)/
  3. var k=text.match(pattern);
  4. alert(k);
  5. //Output: apple1->test();

同時比對兩個資料, RegExp的「or」 。

(?:pattern1|pattern2) : 同時比對 pattern1 與 pattern2,兩個 pattern 只要有一個符合,那麼就算是比對成功,比對到的 pattern 字串,在 Match 這個 Method 中是會被擷取出來的

另外有一個比較簡單的寫法 (pattern1|pattern2)

Example
  1. //兩種function宣告方式,都會比對成功
  2. var text="apple1->test();
  3. apple2::test();";
  4. var pattern=/[a-z0-9]+(?:->|\:\:)/g
  5. var k=text.match(pattern);
  6. alert(k);
  7. //Output: apple1->,apple2::

Parse HTML table

一個 HTML 中通常會有多個 table ,而每個 table 之間又存在各種文字,這時候就要用到 non-greedy 的寫法,就是在 * (星號)後面加一個 ? ,另外用 [\s\S] 來處理多行文字。

Example
  1. var html = `
  2. <table>
  3. <td>aaa</td>
  4. </table>
  5. <table>
  6. <td>bbb</td>
  7. </table>
  8.  
  9.  
  10. `;
  11.  
  12. var reg = /<table[.\n\r\s\S]*?<\/table>/g;
  13. var r = html.match(reg);
  14. console.log(r);

網頁好讀版