正则表达式

2020-04-27  本文已影响0人  倩倩_a570

什么是正则

在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

正则表达式到底能用来做什么

1、测试字符串内的模式。
可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式
2、替换文本。
可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
3、基于模式匹配从字符串中提取子字符串。

1 RegExp对象
2 元字符

+ * ? $ ^ . | \ ( ) { } [ ]

字符 含义
\t 水平制表符
\v 垂直制表符
\n 换行符
\r 回车符
3 字符类

3-1. 字符组
一般情况下 正则中的一个字符对应一个字符串。

'abcdef'.match(/abc/g);  //["abc"]

但是我们有的时候希望匹配某类字符就需要用到字符组(字符类),例如匹配一个字符,它可以是“a”、“b”、“c”其中之一。

'abcdef'.match(/[abc]/g);  //["a", "b", "c"]

3-2. 字符范围
连字符-来省略和简写。[0-9] [a-z] [A-Z]
比如[123456abcdefGHIJKLM],可以写成[1-6a-fG-M]
注意 如果要匹配字符串中的"-" ,将"-"写在范围后面即可

'2020-04-04'.replace(/[0-9-]/g,'A');//"AAAAAAAAAA"

3-3 排除字符组
某位字符可以是任何东西,但就不能是"a"、"b"、"c"。[^abc],表示是一个除"a"、"b"、"c"之外的任意一个字符。字符组的第一位放^(脱字符),表示求反的概念。

'ABCDEF0123'.replace(/[^A-D]/g,'0'); //"ABCD000000"

3-4预定义类

字符 含义
\d [0-9]表示是一位数字。d是digit的简写
\D 就是[^0-9]。表示除数字外的任意字符。
\w 就是[0-9a-zA-Z_]。表示数字、大小写字母和下划线。w是word的简写
\W 是[^0-9a-zA-Z_]。非单词字符
\s 是[ \t\v\n\r\f]。表示空白符。s是space character的简写。
\S 是[^ \t\v\n\r\f]。 非空白符
. 通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。

如果要匹配任意字符怎么办?可以使用[\d\D]、[\w\W]、[\s\S]和[^]中任何的一个。

//将数字替换成A
'ABCDEF0123'.replace(/[\d]/g,'A');//"ABCDEFAAAA"
//将非数字替换成X
'ABCDEF0123'.replace(/[\D]/g,'X');//"XXXXXX0123"
4 量词
字符 含义
? 0次或一次
+ 至少出现一次
* 任意次
{n} 出现n次
{n, m} 出现n到m次。
{n, } 至少出现n次
//匹配8位数字的QQ号码
/^\d{8}$/g.test('12345678'); //true
//匹配1开头11位数字的手机号码
/^1\d{10}$/g.test('12345678910'); //true
//匹配银行卡号是14~18位的数字:
/^\d{14,18}$/g.test('12345678901234567'); //true
//匹配以a开头的,0个或多个b结尾的字符串
/^0b*$/g.test('0bbbb'); //true

贪婪匹配和惰性匹配
正则是贪婪模式,会尽可能多的匹配。

var regex = /\d{2,5}/g;
var string = "123456";
console.log( string.match(regex) ); //["12345"]

而惰性匹配,就是尽可能少的匹配,通过在量词后面加个问号就能实现惰性匹配,因此所有惰性匹配情形如下:

var regex = /\d{2,5}?/g;
var string = "123456";
console.log( string.match(regex) ); //["12", "34", "56"]
5边界
字符 含义
^ 匹配开头,在多行匹配中匹配行开头
$ 匹配结尾,在多行匹配中匹配行结尾
\b boundary ,单词边界
\B \B就是\b的反面的意思,非单词边界
(?=p) 正向先行断言,也叫正向前瞻。其中p是一个子模式,即p前面的位置
(?!p) 负向先行断言,也叫负向前瞻。即p后面的位置

^和&

//比如我们把字符串的开头和结尾用"#"替换
var result = "hello".replace(/^|$/g, '#');
console.log(result); //  "#hello#"

\b和\B

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

\b是单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和$之间的位置。
首先,我们知道,\w是字符组[0-9a-zA-Z_]的简写形式,即\w是字母数字或者下划线的中任何一个字符。
而\W是排除字符组[^0-9a-zA-Z_]的简写形式,即\W是\w以外的任何一个字符。
此时我们可以看看"[#JS#] #Lesson_01#.#mp4#"中的每一个"#",是怎么来的。

1.第一个"#",两边是"["与"J",是\W和\w之间的位置。
2.第二个"#",两边是"S"与"]",也就是\w和\W之间的位置。
3.第三个"#",两边是空格与"L",也就是\W和\w之间的位置。
4.第四个"#",两边是"1"与".",也就是\w和\W之间的位置。
5.第五个"#",两边是"."与"m",也就是\W和\w之间的位置。
6.第六个"#",其对应的位置是结尾,但其前面的字符"4"是\w,即\w和$之间的位置。
\B就是\b的反面的意思,非单词边界。例如在字符串中所有位置中,扣掉\b,剩下的都是\B的。

再举个例子,要将"This is an apple."中的is替换成"X"。

'This is an apple'.replace(/is/,'X');//"ThX is an apple"

这样会将单词中的is 一起匹配替换掉,如果指向匹配 单词"is"

'This is an apple'.replace(/\bis\b/,'X');//"This X an apple"

如果只想讲"This"中的"is"替换掉

'This is an apple'.replace(/\Bis/,'X');//"ThX is an apple"

(?=p)和(?!p)
(?=X),表示前面是'X'字符的位置,(?!X)表示前面不是'X'字符位置例如:

'ABCD'.replace(/(?=D)/,"X");//"ABCXD"
'ABCD'.replace(/(?!B)/g,"X");//"XABXCXDX"

*注意正则表达式从文本头部向尾部开始解析,文本尾部方向称为前。前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言。(和正常理解的前后不同,要注意一下)

6正则中的括号

分组
量词是作用于紧挨着的字符,例如/^ab+$/ 会匹配到'abbb' 而不是'abab'
如果我们想匹配到'abab' 就要用/^(ab)+$/

/^ab+$/.test('abab'); //false
/^ab+$/.test('abbb'); //false

/^(ab)+$/.test('abab'); //true
/^(ab)+$/.test('abbb'); //false

分支结构
或'|': 多个分支可以走任意一个 (aaa | bbb)

'JasperDasper'.replace(/(J|D)asper/g,'X'); //"XX"

如果不加括号则是匹配到'|' 前后的所有字符

var regex = /^I love (JavaScript|Regular Expression)$/;
console.log( regex.test("I love JavaScript") );//true
console.log( regex.test("I love Regular Expression") );//true

引用

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
string.replace(regex,'$1/$2/$3'); //"2017/06/12"
string.replace(regex,'$2/$3/$1'); //"06/12/2017"

上例中,我们用()将表达式分为了三组,在replace方法中$1、$2、$3指代相应的分组。

反向引用
正则本身里引用分组。但只能引用之前出现的分组,即反向引用。
例如需要验证"2017-06-12","2017/06/12" "2017.06.12" "2016-06/12",这几种格式的日期,我们可以用/\d{4}(-|/|.)\d{2}\1\d{2}/,其中(-|/|.)是一个分组,而\1就是引用的该分组的内容

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
var string1 = "2017-06-12";
var string2 = "2017/06/12";
var string3 = "2017.06.12";
var string4 = "2016-06/12";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // true
console.log( regex.test(string4) ); // false

非捕获分组
也称为忽略分组,不希望捕获某些分组时,只需要在分组内加上?:即可
例如 (?:Byron).(ok) 在引用\1时 ,会引用到(ok),分组 (?:Byron).已被忽略。

常用方法

属性
global:是否全文搜索,默认false
ignore case:是否大小写敏感,默认false
multiline:多行搜索,默认值是false
lastIndex:是当前表达式匹配内容的最后一个字符的下一个位置
source:正则表达式的文本字符串

var reg1 = /\w/;
var reg2 = /\w/gim;
reg1.global;//false
reg2.global://true
reg1.ignoreCase://false
reg2.ignoreCase:;//true
reg1.multiline;//false
reg2.multiline;//true
reg1.lastIndex;//0
reg2.lastIndex;//0
reg1.source;//"\w"
reg2.source;//"\w"

在RegExp对象中:
1:test
定义:检测一个字符串是否匹配某个模式。

/(abc)+/.test("abc123") // true

2:exec
定义:检索字符串中的正则表达式的匹配。

如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。

/([a-z])+(\d)+/.exec("abc123abc123abc123") // ["abc123", "c", "3", index: 0, input: "abc123abc123abc123", groups: undefined]

非全局匹配:
第 0 个元素是与正则表达式相匹配的文本,
第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本
第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本
index 属性声明的是匹配文本的第一个字符的位置。
input 属性则存放的是被检索的字符串 string。

var str = 'asd1adf2ad3sdc4'
var reg2 = /\d/g;
reg2.exec(str);//["1", index: 3, input: "asd1adf2ad3sdc4", groups: undefined]
reg2.exec(str);//["2", index: 7, input: "asd1adf2ad3sdc4", groups: undefined]
reg2.lastIndex;//8
reg2.lastIndex = 1;
reg2.exec(str);//["1", index: 3, input: "asd1adf2ad3sdc4", groups: undefined]

全局匹配:
全局匹配模式下,此方法返回值依然是一个数组。和非全局匹配模式下完全一样。
lastIndex属性用来规定正则表达式在字符串中开始检索的位置。
exec方法可以与lastIndex属性配合使用。
如果正则表达式匹配失败,那么lastIndex属性被重置为0。

在String对象中:
1:search
定义:检索字符串中与指定的子字符串或正则表达式相匹配的子字符串。
其他说明:该方法将忽略"g"标志和正则对象的lastIndex属性(即总是从开头找起),返回找到的第一个字符的位置,如果未找到返回-1。
2:match
定义:在字符串内查找一个或多个与正则表达式匹配的字符串,返回一个对象。
非全局调用,返回一个对象,和exec非全局搜索时一样。
全局调用时,返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。

var str="1 plus 2 equal 3"
console.log(str.match(/\d+/g));//["1", "2", "3"]

3:replace(yourRegexpOrString,placementString);
定义:用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
stringObject.replace(regexp/substr,replacement)
replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的 字符具有特定的含义。1、$2、 与 regexp 匹配的子表达式的文本。

var string = 'className';
string.replace(/[A-Z]/g,'x');//"classxame"
var string 1 = 'world, hello';
string1.replace(/(\w+)(?:\W*)(\w+)/,'$2 $1');//"hello world"
var name = 'aaa bbb ccc';
name.replace(/\b\w+\b/g, function(word){
  return word.substring(0,1).toUpperCase()+word.substring(1);
});//"Aaa Bbb Ccc"

4:split
定义:把一个字符串分割成字符串值的数组。
是arr.join(separatorString)反操作,如果传入"",则每个字符都将会被分隔到数组。howMany指定返回数组的个数。

var a= 'banana';
a.split(/a/);//["b", "n", "n", ""]

如果正则表达式包含子表达式,那么返回的数组中包括与这些子表达式匹配的字串。

var a= 'banana';
a.split(/b(a)/);//["", "a", "nana"]
a.split(/a/);//["b", "n", "n", ""]
a.split(/a(n)/);//["b", "n", "", "n", "a"]

参考链接:https://juejin.im/post/5965943ff265da6c30653879

上一篇下一篇

猜你喜欢

热点阅读