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);

网页好读版