正则表达式

基本语法

regular expression是计算机科学中的一个概念。正则表达式使用单个字符串来描述匹配一系列符合某个句法规则的字符串。

创建

  • 构造函数
    var reg = new RegExp('<%[^%>]+%>','g');
  • 字面量
    var reg = /<%[^%]%>/g;

g全文搜索,i忽略大小写,m多行搜索

元字符

字符 含义
\t 水平制表符
\n 换行符
\r 回车符
\f 换页符
\cX 与x对应的控制字符(Ctrl + x)
\v 垂直制表符
\0 空字符

具有特殊意义的专用字符,用来规定其前导字符
( [ { \ ^ $ | ) ? * + .
不同组合中的元字符有不同的意义,举例

字符 含义
\t 水平制表符
\n 换行符
\r 回车符
\f 换页符
\cX 与x对应的控制字符(Ctrl + x)
\v 垂直制表符
\0 空字符

字符类

可以使用[]来构建一个简单的类
var reg = /[abc123]/;
创建一个单字符的类,代表这个字符可以是a,可以是b,可以是c,可以是1,...可以是3。

取反

可以使用^来进行取反,
var reg = /[^abc123]/;
代表着这个单字符可以是任何其他的单字符,除了a,b,c,1,2,3之外。

范围类

如果要匹配单个字符,让单字符只能取数字的话,可以使用字符类
写成:
var reg = /[0123456789]/;
这么写比较麻烦,所以可以使用范围类,我们可以使用x-y来连接两个字符,表示从x到y的任意字符,是个闭区间,意味着包含x和y本身,这样,我们要匹配单个数字就可以写成:
var reg2 = /[0-9]/;
要匹配所以的单个字母,可以写为
var reg3 = /[a-zA-Z]/;

预定义类

上面创建了一些类,用来表示数组,字母等。但是这么写也比较麻烦,正则表达式提供了几个常见的预定义类来匹配常见的字符

字符 等价类 含义
. [^\r\n] 除了回车符和换行符之外的所有字符
\d [0-9] 数字字符
\D [^0-9] 非数字字符
\s [\t\n\x0B\f\r] 空白符
\S [^\t\n\x0B\f\r] 非空白符
\w [a-zA-Z_0-9] 单词字符,字母,数字下划线
\W [^a-zA-Z_0-9] 非单词字符

有了这些预定义类,写一些正则就比较方便了,比如我们希望匹配一个ab+数字+任意字符的字符串,就可以写作:
var reg = /ab\d./;

边界

正则表达式还提供了几个常用的边界匹配字符

字符 含义
^ 以xxx开头
$ 以xxx结尾
\b 单词边界
\B 非单词边界

^如果不写在[]内的话,不代表取反,代表以xxx开头,例如:var reg = /hello/;代表以hello开头,相应的也有$表示为以xxx结尾,举例说明:


    var reg = /^h\dm/g;
    var str = 'h3m h4m h2m';
    console.log(str.match(reg));// ["h3m"] 只匹配了第一个h\dm,因为有^
    var reg2 = /h\dm$/g; // $代表以xxx结尾
    console.log(str.match(reg2));//["h2m"] / 只匹配了最后一个h\dm  因为有$
    var reg3 = /^h\dm$/g; //代表既以h\dm开头,又以h\dm结尾的
    console.log(str.match(reg3)); // null 匹配不到

    //关于既有开头又有结尾的例子 比如匹配手机号 以1开头,以10个数字结尾
    var phoneReg = /^1\d{10}$/;  //\d{10}代表10个数字
    var phoneStr = '13892229999';
    console.log(phoneStr.match(phoneReg)); //"13892229999" 匹配不到返回null

单词边界

    var str = 'hello worhellold hello';
    var reg  = /hello/g;
    console.log(str.match(reg)); // ["hello", "hello", "hello"] 会将3个hello都匹配到,但是如果想要只匹配单词hello的话要使用\b
    var reg2 = /\bhello/g;
    console.log(str.match(reg2)); // ["hello", "hello"] 只匹配到了单词hello
    var str2 = 'hello wor-hello-ld hello'; // 写成如此格式,也被识别为合法的单词
    console.log(str2.match(reg2)); // ["hello", "hello", "hello"] 这么写也被识别为合法的,所以匹配到了3个hello单词

量词

之前写的方法都是一一匹配的,但是如果希望匹配一个连续出现很多次的字符,例如数字的字符串,不需要写成\d\d\d\d,我们可以使用量词

字符 含义
? 出现一次或者0次(最多出现一次)
+ 出现一次或者多次(最少出现一次)
* 出现0次或者多次(任意次)
{n} 出现n次
{n,m} 出现n到m次
{n,} 至少出现n次
{,m} 最多出现m次

使用举例:

    var reg = /[a-z]\d?/g; // ?代表最多出现一次
    console.log('a12345b678cde'.match(reg)); //["a1", "b6", "c", "d", "e"] 因为后面的\d? 有?存在,即最多出现一次,所以后面的cde没有数字也可以被匹配到
    var reg2 = /[a-z]\d+/g;
    console.log('a12345b678cde'.match(reg2));//["a12345", "b678"],+为最少出现一次,则a,b后面的有多少都可以匹配到,cde后面没有数字所以匹配不到
    var reg3 = /[a-z]\d*/g;
    console.log('a12345b678cde'.match(reg3));//["a12345", "b678", "c", "d", "e"] *代表可以有任意多次,包括0,所以都能匹配到

    var reg4 = /[a-z]\d{4}/g; //匹配字母后面4个字符
    console.log('a12345b678cde'.match(reg4));//["a1234"]
    var reg5 = /[a-z]\d{1,3}/g; //匹配字母后面1-3个字符
    console.log('a12345b678cde'.match(reg5)); // ["a123", "b678"] 1-3尽量多的去匹配,3个没有就2个,逐渐减小,先匹配多的

贪婪模式 非贪婪模式

上面提到的{n,m},如果出现多次,只要是n-m中的值都满足条件,到底是按照n还是m来匹配。 量词在默认条件下是尽可能多的匹配的,即默认贪婪模式
var reg = /\d{3,5}/g; '123456789'.match(reg); //{"12345","6789"}

与贪婪模式相对的,就有非贪婪模式,即尽可能少的匹配,一旦成功匹配之后不再继续尝试,在后面加上?即可
var reg2 = /\d{3,5}?/g; '123456789'.match(reg); //{"12345","6789"}

分组

上面的量词解决的是单个字符重复多次的问题,如果我们需要匹配重复的多个字符,比如匹配hello出现20次,如果写成hello{20}意味着是hell+o出现20次,o自己重复20次,而不是整个hello重复20次。

我们可以使用分组()来解决这个问题,写成:
/(hello){20}/g;

对于上面的情况,如果我们希望匹配hello或者world出现20次,可以通过使用 | 进行或操作
/(hello|world){20}/g;

前瞻

表达式 含义
exp1(?=exp2) 匹配后面是exp2的exp1
exp1(?!exp2) 匹配后面不是exp2的exp1

举例:good(?=Bayon)匹配后面有Bayon的good

    var reg = /good(?=Bayon)/;
    reg.exec('goodBayon123'); // ['good']
    reg.exec('goodCasper123'); // null

正则表达式的一些相关方法

RegExp.prototype.test(str)

检测字符串参数中是否存在正则表达式模式,存在返回true不存在返回false

    var reg = /hello/; //用来检验字符串 匹配成功了返回true
    console.log(reg.test('hello world')); //true
    //具体应用举例,用来判断是否为手机号
    function isPhoneNumber (str) {
        if (/^1\d{10}$/g.test(str)) { //匹配到手机号时返回true
           console.log('是合法的手机号码');
        }
    }
    isPhoneNumber('13812345678');

RegExp.prototype.exec(str)

用于正则表达式模式在字符串中运行查找,如果exec()找到了匹配的文本,则返回一个结果数组,否则返回null
除了数组元素和length属性之外,exec()方法返回对象还包括两个属性。

  • index 属性声明的是匹配文本的第一个字符的位置
  • input属性则存放的是被检索的字符串string

举例说明:

    var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
    var reg = /h[a-z]llo/g;
    var result = reg.exec(str);
    console.log(result);//["hallo", index: 0, input: "hallo deejay,hbllo world,hcllo daisy"]
    result = reg.exec(str);
    console.log(result);//["hbllo", index: 13, input: "hallo deejay,hbllo world,hcllo daisy"]
    result = reg.exec(str);
    console.log(result);//["hcllo", index: 25, input: "hallo deejay,hbllo world,hcllo daisy"]

String.prototype.search(reg)

search()方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。
search方法不执行全局匹配,它将忽略标志g,同时也忽略正则表达式对象的lastIndex属性,总是返回字符串的第一个匹配的位置

String.prototype.match(reg)

match()方法将检索字符串,以找到一个或者多个与regexp匹配的文本。regexp是否有全局g标志会影响结果。

String.prototype.replace(reg,replaceStr)

关于string对象的replace方法,一般可以传入两个字符串,但是只能replace一次,如果把第一个参数传入regexp的话,就可以是replace变得灵活。

    var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
    var reg = /h[a-z]llo/g;
    str = str.replace(reg,'hello'); // 传入的第一个参数为regexp,找到匹配的字符串替换成hello
  • String.prototype.replace(reg,function)
    当replace方法的第二个参数为function的时候,这个function会在每次替换的时候调用。
    var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
    var reg = /h[a-z]llo/g;
    str = str.replace(reg,function (value) {
        console.log(arguments);
        return value[0].toUpperCase() + value.substring(1,value.length);
    })
    console.log(str); //Hallo deejay,Hbllo world,Hcllo daisy

String.prototype.split(reg)

经常使用split方法把字符串分割为字符数组
'a,b,c,d'.split(","); // ["a","b","c","d"];
相应的,也可以使用regexp进行切割:
"a1b2c3".split(/\d/); // ["a","b","c","d"]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容