正则表达式的学习

2017-10-21  本文已影响0人  白璞1024

一、位置匹配攻略

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
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 = /(?=.*\d)(?=.*[A-Z])|(?=.*\d)(?=.*[a-z])|(?=.*[A-Z])(?=.*[a-z])^[1-9a-zA-Z]{6,12}$/

二、括号的作用

1、 分组和分支结构

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"

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相关案例

 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
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会产生回朔的地方有哪些?

四 正则表达式的拆分

1、结构和操作符

js正则表达式的结构:

操作符的优先级:
\转义字符
括号和方括号()、(?:...)(?=) (?!) []
量词和限定符 {} {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 :

RegExp:

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
上一篇 下一篇

猜你喜欢

热点阅读