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