何谓 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 好用的工具。
 
