正则表达式的学习

一、位置匹配攻略

1 如何匹配位置

1.1 开头和结尾 ^$

var result = "hello".replace(/^|$/g,"#");
undefined
console.log(result)
VM3394:1 #hello#

1.2 \b 和 \B

\b是单词边界,具体就是\w和\W之间的位置,


var result = "[JS] Lesson_01.mp4".replace(/\b/g,"#");
console.log(result)
VM3462:2 [#JS#] #Lesson_01#.#mp4#

\B与之相反

var result = "[JS] Lesson_01.mp4".replace(/\B/g,"#");
console.log(result);
#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4

1.3 (?=p) 和 (?!p)

(?=p) p是一个子模式,也就是p前边的位置,或者说该位置后边的字符要匹配 p .
简单来说就是p前边的那个位置

(?!) 表示l字符前面的字符
除了p 其他字符前边的位置

var result = "hello".replace(/(?=l)/g,"#");
console.log(result);
he#l#lo


var result = "hello".replace(/(?!l)/g,"#");
console.log(result)
#h#ell#o#

2、位置的特性

把位置理解成一个空字符串可以试试

var result = /(?=he)^^he(?=\w)llo$\b\b$/.test("hello")
console.log(result)
true

3、相关案例

3.1 不匹配任何东西的正则

类似于:/.^/

3.2数字的千分位分隔符表示法

把12345678变成12,345,678

  • 弄出最后一个逗号
var result = "12345678".replace(/(?=\d{3}$)/g,",");
console.log(result)
12345,678
  • 弄出所有的逗号
var result = "12345678".replace(/(?=(\d{3})+$)/g,",");
console.log(result);
 12,345,678
  • 匹配其他的案例
var result = "123456789".replace(/(?=(\d{3})+$)/g,",");
undefined
console.log(result)
 ,123,456,789 这样有bug所以需要改进
var result = "123456789".replace(regex,",");
var result2 = "12345678".replace(regex,",");
console.log(result)
console.log(result2)
 123,456,789
 12,345,678
  • 如果输入的数字是:12,345,678呢?
    也就是要求匹配单词边界
    后头的\b是为了后头连着单词边界,也就是从后往前找
    前边的\B表示前边不能是单词边界也就是第一个不能是逗号
var result = "123456,789".replace(/(\B)(?=(\d{3})+\b)/g,",");

console.log(result)
123,456,789

3.3 金额格式化

var a = 1999;

var b = a.toFixed(2).replace(/\B(?=(\d{3})+\b)/,",").replace(/^/,"$$ ");
undefined
console.log(b)
VM4095:1 $ 1,999.00

toFixed是一个数字的函数,他返回了的是一个字符串,然后参数是小数的位数

3.4 验证密码的问题

要求:6-12 数字 大写字母 小写字母 至少包括两种字符

  • 简化 不考虑至少包括两种字符这一条件
    var regex = /^[0-9A-Za-z]{6,13} $/g

  • 判断是不是包某种字符
    (如果必须包含的是数字的话)
    var regex = /(?=.*\d)^[1-9a-zA-Z]{6,12}$/

  • 同时包含两种字符
    var regex = /(?=.*\d)(?=.*[a-z])^[1-9a-zA-Z]{6,12}$/

  • 解答

    • 包含数字和小写字母
    • 包含数字和大写字母
    • 包含小写字母和大写字母
    • 数字 小写 大写

var regex = /(?=.*\d)(?=.*[A-Z])|(?=.*\d)(?=.*[a-z])|(?=.*[A-Z])(?=.*[a-z])^[1-9a-zA-Z]{6,12}$/

二、括号的作用

1、 分组和分支结构

  • 1.1 分组
    要匹配连续出现的ab时候就需要 /(ab)+/
  • 1.2 分支
    (p1|p2)

2、分组引用

我们可以进行数据提取,以及更强大的替换操作

/(\d{4})-(\d{2})-(\d{2})/
括号相当于多了一个分组
正则引擎也是这么做的,匹配过程中,给每一个分组都开辟一个空间用来储存每一个分组匹配到的数据

2.1 提取数据

  • 提取出年月日
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2014-21-12"
console.log(string.match(regex))
["2014-21-12", "2014", "21", "12", index: 0, input: "2014-21-12"]

match方法第一个元素是整体匹配的结果,然后是各个分组(括号里)匹配的内容,然后是匹配下标最后是输入文本

正则的时候里边是否有g,match返回的数组格式是不一样的

也可以使用正则实例对象的exec方法:

console.log(regex.exec(string))
(4) ["2014-21-12", "2014", "21", "12", index: 0, input: "2014-21-12"]


regex.exec(string)
(4) ["2014-21-12", "2014", "21", "12", index: 0, input: "2014-21-12"]
console.log(RegExp.$2)
21

但是取值的时候,只有第一个数有值

2.2 替换

yyyy-mm-dd格式,替换成mm/dd/yyyy

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2014-21-12";
var result = string.replace(regex,"$2/$3/$1");
console.log(result)
 21/12/2014

另一种方法

var result = string.replace(regex,function(match,year,month,day){
    return month+"/"+day+"/"+year;
})
console.log(result)
 21/12/2014

2.3 反向引用

除了使用相应的api来分株,也可以在正则本身里引用分株,但是只能用之前出现的分组,也就是反向引用

写一个正则支持匹配下面的三种格式
2012-12-12
2012/12/12
2012.12.12
第一个方法:

var regex  = \d{4}(-|\.|\/)\d{2}\(-|\.|\/)\d{2};

这样就匹配的2012/12-12这样的数据

如果前后分隔符一致怎么办,
反向引用就可以实现了

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/; 

这里的\1表示前边的那个括号里不管匹配上的是什么值 \1都匹配了同样的摸个具体的字符

2.3.1 括号嵌套?

以左括号为准
var regex = /^((\d)(\d(\d)))\1\2\3$/
var string = "123123123"

  • \1 表示123
  • \2 表示 第一个\d 1
  • \3 (\d(\d)) 23
  • \4 3

2.3.2 \10表示什么

分组10 还是 \1 0

var regex = /(1)(2)(3)(4)(5)(6)(7)(8)(9)(#) \10+/
var string = "123456789# ######################################"
console.log(regex.test(string))

如果需匹配\1 0的话,请使用(?:\1)0 或者 \1(?:0)

2.3.3 引用不存在的分组

如果没有\2那就么就匹配\2表示对2进行了转义

2.3.4 非捕获括号

只用原始的功能,不去引用他,也不再正反向引用,非捕获括号
(?:p)

2.4相关案例

  • trim方法模拟
 function trim(str){
    return str.replace(/^\s+|\s+$/g,"")
}

匹配整个字符串,然后应用提取出相应的数据

function trim(str){
    return str.replace(/^\s*(.*?)\s*$/g,"$1")
}
trim("         1231          ")
"1231"

惰性匹配为了防止最后一个空格之前所有的空格也被匹配上

function trim(str){
    return str.replace(/^\s*(.*)\s*$/g,"$1")
}
trim("         12s      adf    31          ")
"12s      adf    31          "
  • 将首字母大写
function titleize(str){
return str.toLowerCase().replace(/(?:^|\s)\w/g,function(c){
    return c.toUpperCase();
})
}
console.log(titleize("my name is epeli"))
My Name Is Epeli
  • 驼峰化
function camelize(str){
return str.replace(/[-_\s]+(.)?/g,function(match,c){
    return c?c.toUpperCase():"";
})
}
console.log(camelize('-moz-transform'))
MozTransform

这里匹配上的是-m -t但是c的意思是括号中的匹配项

  • 中划线
function dasherize(str){
    return str.replace(/([A-Z])/g,'-$1').replace(/[-_\s]+/g,"-").toLowerCase();
}
console.log(dasherize("MozTransform"))
 -moz-transform
  • html转义和反转义
function escapeHTML(str){
    var escapeCars  = {
        '<':'lt','>':'gt','"':'quot','&':'amp','\`':'#39',
}
return str.replace(new RegExp('['+Object.keys(escapeCars).join('')+']',"g"),function(match){
    return "&"+escapeCars[match]+";";
});
}
console.log(escapeHTML("<div> balh blah blah</div>"))
 &lt;div&gt; balh blah blah&lt;/div&gt;
  • 匹配成对标签

三 回溯法原理

1 没有回溯的匹配

/ab{1,3}c/
目标是abbbc的时候就每一偶回溯,

2 有回溯的匹配

如果是abbc的时候就有问题了

3 常见的形式

本质上就是深度优先搜索算法,退到之前某一步的过程,我们称之为回朔
js会产生回朔的地方有哪些?

  • 贪婪量词

    • console.log("12345".match(/(\d{1,3})([\d]{1,3})/));123 45前边的先下手抢了三个
  • 惰性量词

    • 在贪婪次后头追加一个问号
    • console.log("12345".match(/^(\d{1,3}?)([\d]{1,3})$/));
    • (3) ["12345", "12", "345", index: 0, input: "12345"]
    • 为了让后边的能够匹配上,不得不给前边多匹配一个数字
  • 分支结构
    -/candy|can/ 匹配can的时候前边就进行了部分匹配,后来发现candy匹配不就去第二个分支

四 正则表达式的拆分

1、结构和操作符

js正则表达式的结构:

  • 字符字面变量 具体字符,需要和不需要转义的 a 和,
  • 字符组 匹配一个字符,可以是多种可能之一[0-9] \d [^0-9] \D
  • 量词 表示一个字符连续出现,a{1,3} +
  • 锚 匹配一个位置而不是字符 \b (?=\d)
  • 分组 括号表示一个整体,比如(ab)+ 也可以用非捕获分组(?:ab)
  • 选择分支 sbv|qwe

操作符的优先级:
\转义字符
括号和方括号()、(?:...)(?=) (?!) []
量词和限定符 {} {m,n}{m,} ? * +
位置和序列 ^ $
管道符 |

/ab?(c|de)+|fg/
(c|d
)是一个整体结构
c是整体 de另一个
然后
ab?(c|de
)+ 和fg

2 注意点

2.1 匹配字符串整体的问题

要匹配整个字符串,我们经常会在正则前后加上锚^$
位置的优先级高于|所以
abc或者是bcd的时候^abc|bcd$不对的
要加括号
/(abc|bcd)/

2.2 元字符转义问题

^、$、。、*、 、+、?、|、\、/、(、)、[、]、{、}、=、!、:、-、

var a  = "!@#$%^&*()"
var b =  "\!\@\#\$\%\^\&\*\(\)"
console.log(a==b)
 true

2.3 [] 和{}的问题

var var string = "[abcd]"

var regex = /\[abcd]/g
console.log(string.match(regex)[0])
 [abcd]

1 正则表达式的四种操作

1.1、验证

表单验证什么的,
匹配的本质就是查找,有没有匹配,是不是匹配上判断是否的操作就是验证。
判断一个字符串是否有数字?

var regex = /\d/;
var string = "abc123";
console.log(!!~string.search(regex));
test match search exec

1.2 切分

js中的 split

html,css,javascript按逗号来切分

var regex = /\D/;
var string = "html,css,javascript"
console.log(string.split(regex));
["html","css","javascript"]

1.3 提取

整体匹配上了,但是需要提取部分匹配的数据,正则通常使用分组捕获的功能,需要相关API

var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/
var string ="2014-12-12";
console.log(string.match(regex));
match (4) ["2014-12-12", "2014", "12", "12", index: 0, input: "2014-12-12"]
exec (4) ["2014-12-12", "2014", "12", "12", index: 0, input: "2014-12-12"]
test  console.log(RegExp.$1,RegExp.$2,RegExp.$3) "2014", "12", "12"
search console.log(RegExp.$1,RegExp.$2,RegExp.$3) "2014", "12", "12"
replace **这个需要重点掌握**

2.相关api注意要点

String :

  • search
  • split
  • match
  • replace

RegExp:

  • test
  • exec

2.1 search match参数问题

这俩会把字符串转化为正则,
就是如果search(".")
需要修改为下列形式之一:
search("\.")
search(/./)
match也一样

match返回结果的格式问题

var string = "2014.12.12";
var regex1 = /\b(\d+)\b/;
var regex2 = /\b(\d+)\b/g;
console.log(string.match(regex1))
console.log(string.match(regex2))

(2) ["2014", "2014", index: 0, input: "2014.12.12"]
(3) ["2014", "12", "12"]
没有g的时候,返回的是标准匹配格式,也就是数组的第一个元素师整体匹配的内容,接下来是分株捕获的内容,然后是整体匹配第一个下标,最后是输入的目标字符串
有g 返回的是所有匹配的内容

使用字符串保存数据

一般情况我们都使用数组来保存数据,但看到有的框架中使用的是字符串,使用时,把字符串分切成数组,不一定用正则,分享下

var utils = {};
"Boolean |Nunber| Struing |Function |Array |Date |RegExp|Object|Error".split("|").forEach(
    function(item){
        utils["is"+item]  = function(obj){
            return {}.toString.call(obk) == "[object"+item+"]";
        }
    }
)
console.log(utils.isArray([1,2,3]))

console.log({}.toString.call([1,2,3]))
[object Array]

查询字符串压缩为例子

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

推荐阅读更多精彩内容

  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,993评论 0 20
  • 正则基础 \b 是正则表达式的一个特殊代码,有人称它元字符。代表的是需要匹配的某个单词的开头或者结尾。有些单词有...
    立觉阅读 324评论 0 1
  • 在工作中我们经常遇到这样的需求: 1.给你一个字符串,把字符串里面的链接、数字、电话等显示不同的颜色; 2.给你一...
    编程的蚂蚁阅读 4,943评论 6 7
  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,141评论 0 9
  • 已经是深夜了,仍然没有睡意,老婆和宝宝在床上睡得正酣,风扇摇着头,吹着我们不至于太热。这个时间里,家里安静了下来,...
    语成文阅读 563评论 0 1