正则表达式的学习

一、位置匹配攻略

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值