资讯专栏INFORMATION COLUMN

JavaScript必会技能——正则表达式

FrozenMap / 1549人阅读

摘要:语法参数必填项,字符串或正则表达式,该参数指定的地方分割可选该参数指定返回的数组的最大长度,如果设置了该参数,返回的子字符串不会多于这个参数指定的数组。该数组通过在指定的边界处将字符串分割成子字符串。把正则表达式拆分成小表达式。

正则表达式是什么

RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。

为什么使用正则表达式

测试字符串内的模式。例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。

替换文本。可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

基于模式匹配从字符串中提取子字符串。可以查找文档内或输入域内特定的文本。

语法

正则表达式有两种方法定义:

1.直接量语法

/pattern/attributes

2.创建 RegExp 对象的语法:

new RegExp(pattern, attributes);

参数:参数pattern是一个字符串,指定了正则表达式的模式;参数attributes是一个可选的参数,包含属性g,i,m,分别使用与全局匹配,不区分大小写匹配,多行匹配;
返回值:一个新的RegExp对象,具有指定的模式和标志;

修饰符
修饰符 说明
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
i 执行不分大小写匹配。
m 执行多行匹配。
括号

方括号包含一系列字符,可以匹配它所包含的任意字符;同时可以通过^符号来定义否定字符类

表达式 说明
[abc] 查找在方括号中的任意一个字符
[^abc] 查找不在方括号中的任意一个字符
[0-9] 查找0-9中的任意一个数字
[a-z] 查找任何从小写 a 到小写 z 的字符
[A-Z] 查找任何从大写 a 到大写 z 的字符
(red | blue | green) 查找小括号中的任意一项,小括号中的|是或者的意思
元字符
元字符 说明
. 查找任意的单个字符,除换行符和其他Unicode行终止符之外
w 查找字母数字和下划线 ,等价于[a-zA-Z0-9_]
W 查找除字母数字下划线之外的字符,等价于[^a-zA-Z0-9_]
d 查找数字字符,等价于[0-9]
D 查找非数字字符,等价于[^0-9]
s 匹配任何空白字符,包括空格,制表符,换行符等等。等价于[f v]
S 匹配任何非空白字符,等价于[^f v]
 查找一个单词边界,也就是指单词和空格间的位置,比如er可以匹配"never"中的"er",但是不能匹配"verb"中的"er"
B 查找非单词边界,erB能匹配"ver"中的"er",但不能匹配"never"中的"er"
查找空字符("")
查找换行符
查找回车符
f 查找换页符
查找制表符
v 查找垂直制表符
量词
量词 说明
n+ 匹配任何至少包含一个n的字符串,等价于n{1,}
n* 匹配零个或者多个n的字符串,等价于n{0,}
n? 匹配零个或者1个n的字符串,等价于n{0,1}
n{x} 匹配包含x个n的序列字符串
n{x,y} 匹配至少x个,最多y个n的字符串
n{x,} 匹配至少x个n的字符串
n$ 匹配以n结尾的字符串
^n 匹配以n开头的字符串
正则表达式的特殊字符中需要转义字符

正则表达式中的特殊字符都有它们的特殊含义,所以当我们要匹配这些特殊字符本身时,需要对字符进行转义,转义只需要在字符前面加上,这些特殊字符包括$ ^ * + . [ ? { | ( )

支持正则表达式的方法 RegExp 对象方法

1.test方法:该方法用于检测一个字符串是否匹配某个模式。

语法RegExpObject.test(str)
参数:str是需要检测的字符串
返回值:如果字符串str中含有与RegExpObject匹配的文本的话,返回true,否则返回false

示例代码如下:

var str = "longen and yunxi";
console.log(/longen/.test(str)); // true
console.log(/longlong/.test(str)); //false

2.exec方法:该方法用于检索字符串中的正则表达式的匹配。

语法RegExpObject.exec(str)
参数:str是需要检测的字符串
返回值:返回一个数组,存放匹配的结果,如果未找到匹配,则返回值为null

示例代码如下:

var str = "javascript html css";
console.log(/html/.exec(str)); // ["html", index: 11, input: "javascript html css"]
返回的数组的第一个元素是与正则表达式相匹配的文本,该方法还返回2个属性,index属性声明的是匹配文本的第一个字符的位置;input属性则存放的是被检索的字符串string。

// 假如没有找到的话,则返回null
console.log(/node/.exec(str)); // null
支持正则表达式的 String 对象的方法

1.search方法:该方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的字符串。

语法stringObject.search(regexp)
参数:regexp可以是在stringObject中检索的字符串,也可以是需要检索的RegExp对象
返回值:stringObject中第一个与regexp对象相匹配的子串的起始位置。如果没有找到任何匹配的子串,则返回-1;

示例代码如下:

var str = "hello world,hello world";
// 返回匹配到的第一个位置
console.log(str.search(/hello/)); // 0
// search方法不执行全局匹配,它将忽略标志g,同时它也没有regexp对象的lastIndex的属性,且总是从字符串开始位置进行查找,总是返回的是stringObject匹配的第一个位置。
console.log(str.search(/hello/g)); //0
console.log(str.search(/world/)); // 6

// 也可以是检索字符串中的字符
console.log(str.search("wo")); // 6

// 如果没有检索到的话,则返回-1
console.log(str.search(/longen/)); // -1

// 我们检索的时候 可以忽略大小写来检索
var str2 = "Hello";
console.log(str2.search(/hello/i)); // 0

2.match方法:该方法用于在字符串内检索指定的值,或找到一个或者多个正则表达式的匹配。该方法类似于indexOf()或者lastIndexOf(); 但是它返回的是指定的值,而不是字符串的位置。

语法stringObject.match(regexp)
参数:regexp可以是在stringObject中检索的字符串,也可以是需要检索的RegExp对象
返回值:存放匹配成功的数组;如果没有找到任何的一个匹配,那么它将返回的是null。

示例代码如下:

var str = "hello world";
// 返回的数组内有三个元素,第一个元素的存放的是匹配的文本,还有二个对象属性;index属性表明的是匹配文本的起始字符在stringObject中的位置;input属性声明的是对stringObject对象的引用;
console.log(str.match("hello")); // ["hello", index: 0, input: "hello world"]
console.log(str.match("Hello")); // null
console.log(str.match(/hello/)); // ["hello", index: 0, input: "hello world"]

// 全局匹配也返回一个数组,但有些不一样;它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。
var str2="1 plus 2 equal 3"
console.log(str2.match(/d+/g)); //["1", "2", "3"]

3.replace方法:该方法用于在字符串中使用一些字符替换另一些字符,或者替换一个与正则表达式匹配的子字符串。

语法stringObject.replace(regexp/substr,replacement);
参数:regexp/substr可以是字符串或者是需要替换模式的RegExp对象;replacement可以是替换的文本或者是生成替换文本的函数。
返回值:返回替换后的新字符串。

字符串 stringObject 的 replace() 方法执行的是查找并替换的操作。它将在 stringObject 中查找与regexp 相匹配的子字符串,然后用 replacement 来替换这些子串。如果 regexp 具有全局标志 g,那么replace() 方法将替换所有匹配的子串。否则,它只替换第一个匹配子串。

replacement可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的 $字符具有特定的含义。如下表所示,它说明从模式匹配得到的字符串将用于替换。

字符 含义
$1$2、...、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
$& 与 regexp 相匹配的子串。
$` 位于匹配子串左侧的文本。
$" 位于匹配子串右侧的文本。
$$ 表示美元符号$。

示例代码如下:

var str = "hello world";
// 使用字符串替换字符串
var s1 = str.replace("hello","a");
console.log(s1);// a world

// 使用正则替换字符串
var s2 = str.replace(/hello/,"b");
console.log(s2); // b world

// 使用正则全局替换字符串
var s3 = str.replace(/l/g,"");
console.log(s3); // heo word

// $1,$2 代表的是第一个和第二个子表达式相匹配的文本
// 子表达式需要使用小括号括起来,代表的含义是分组
var name = "longen    ,yunxi";
var s4 = name.replace(/(w+)s*,s*(w+)/,"$2 $1");
console.log(s4); // "yunxi,longen"

console.log("hello world".replace(/w/g, "$&")) //hello world
console.log("hello world".replace(/w/g, "$$")) //hello $orld
console.log("hello world".replace(/w/g, "$`")) //hello hello orld
console.log("hello world".replace(/w/g, "$"")) //hello orldorld

// replace 第二个参数也可以是一个function 函数
// 单词首字母大写
var name = "aaa bbb ccc";
var uw=name.replace(/w+/g, function(word){
    return word.substring(0,1).toUpperCase()+word.substring(1);}
);
console.log(uw) //Aaa Bbb Ccc


var name2 = "123cbc45678rtyu909876pjkl54321";
name2.replace(/d+/g,function(v){
    console.log(v); 
    /*
     * 第一次打印123
     * 第二次打印45678
     * 第三次打印909876
     * 第四次打印54321
     */
});
/*
 * 如下函数,回调函数参数一共有四个
 * 第一个参数的含义是 匹配的字符串
 * 第二个参数的含义是 正则表达式分组内容,没有分组的话,就没有该参数,
 * 如果没有该参数的话那么第四个参数就是undefined
 * 第三个参数的含义是 匹配项在字符串中的索引index
 * 第四个参数的含义是 原字符串
 */
 name2.replace(/(d+)/g,function(a,b,c,d){
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);
    /*
     * 如上会执行四次,值分别如下(正则使用小括号,代表分组):
     * 第一次: 123,123,0,123cbc45678rtyu909876pjkl54321
     * 第二次: 45678,45678,6,123cbc45678rtyu909876pjkl54321
     * 第三次: 909876,909876,15,123cbc45678rtyu909876pjkl54321
     * 第四次: 54321,54321,25,123cbc45678rtyu909876pjkl54321
     */
 });

4.split方法:该方法把一个字符串分割成字符串数组。

语法stringObject.split(separator,howmany)
参数
1.separator[必填项],字符串或正则表达式,该参数指定的地方分割stringObject;
2.howmany[可选] 该参数指定返回的数组的最大长度,如果设置了该参数,返回的子字符串不会多于这个参数指定的数组。如果没有设置该参数的话,整个字符串都会被分割,不考虑他的长度。
返回值:一个字符串数组。该数组通过在separator指定的边界处将字符串stringObject分割成子字符串。

示例代码如下:

var str="How are you doing today?"
console.log(str.split(" ")) //["How", "are", "you", "doing", "today?"]
console.log(str.split("")) //["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y", "?"]
console.log(str.split(" ",3)) //["How", "are", "you"]

// 也可以使用正则表达式
console.log(str.split(/s+/)) //["How", "are", "you", "doing", "today?"]
贪婪模式与非贪婪模式

Javascript中的正则表达式贪婪模式与非贪婪模式的区别是:被量词修饰的子表达式的匹配行为;贪婪模式在整个表达式匹配成功的情况下尽可能多的匹配;非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。

一些常见的修饰贪婪模式的量词如下:
{x,y}{x,}?*+

非贪婪模式就是在如上贪婪模式后加上一个问号(?),就可以变成非贪婪模式的量词;如下:
{x,y}?{x,}???*?,和+?

示例代码如下:

//贪婪模式,尽可能多的匹配
console.log("0123456789".replace(/d{3,6}/,"*")) //*6789

//非贪婪模式,尽可能少的匹配
console.log("0123456789".replace(/d{3,6}?/,"*")) //*3456789
分组与反向引用

分组,又称为子表达式。把正则表达式拆分成小表达式。

直接上代码:

//不分组,量词仅作用到最后一个字符(c)
console.log(/abc{2}/.test("abcabc")); // false
console.log(/abc{2}/.test("abcc")); //true

//分组,量词作用于整个括号里的子表达式
console.log(/(abc){2}/.test("abcabc")); // true
console.log(/(abc){2}/.test("abcc")); //false

分组经常和反向引用一起使用,反向引用在前面的replace方法就有了,只不过没有说他的概念,这里说一下:当一个正则表达式被分组后,每个分组自动被赋予一个组号,一左到右分别是 $1 $2…
再举个例子:

//格式化日期
var reg = /^(d{4})[/-](d{2})[/-](d{2})$/
console.log("2016/11/18".replace(reg, "$1年$2月$3日")) //2016年11月18日
console.log("2016-11-18".replace(reg, "$1年$2月$3日")) //2016年11月18日
console.log("2016-11-18".replace(reg, "$1$2$3")) //20161118
非捕获性分组

不是所有分组都能创建反向引用,有一种分组叫做非捕获性分组,非捕获性分组以(?:pattern)表示,在一些只需要分组匹配但是并不需要得到各个分组匹配的结果时,使用非捕获性分组可以提高匹配速度;非捕获分组的含义我们可以理解为如下:子表达式可以作为被整体修饰但是子表达式匹配的结果不会被存储;如下:

var reg = /(?:d{4})-(d{2})-(d{2})/
var date = "2012-12-21"
reg.test(date)
RegExp.$1  // 12
RegExp.$2  // 21

这里,(?:d{4})分组不会捕获任何字符串,所以$1(d{2})捕获的字符串。

零宽断言

初学者第一次看到这个名词可能有点懵逼(我第一次也不懂),这里说明一下。

零宽断言就是下结论,例如ab,正则:a(?=b),匹配a并且向右看是b,得到的结果是a,断言不会在匹配的内容当中,如果是a(?=c),则匹配不到任何内容,因为匹配a以后向右看并不是c。另外,零宽断言分两种:前瞻(Lookahead)和后顾(Lookbehind);但JavaScript只支持前瞻

前瞻表达式的语法如下:

表达式 说明
m(?=n) 匹配后面紧接n的字符串m
m(?!n) 匹配后面没有紧接n的字符串m

再两个例子:

// 获取字符串中以ing结尾的单词的前半部分
var str = "I love dancing but he likes singing";
var pattern = /w+(?=ing)/g;
var ans = str.match(pattern);
console.log(ans); // ["danc", "sing"]


// 获取第五位不是i的单词的前四位
var s = "I love dancing but he likes singing";
var pattern = /w{4}(?!i)/g;
var ans = s.match(pattern);
console.log(ans); // ["love", "like"]
最后

正则表达式基础知识差不多这些够用了,后面就是多谢多运用。共勉!

推荐

最后推荐两个比较好的工具,能帮助我们写出更好更准确的正则表达式。
正则表达式图形化工具
正则表达式检测工具

博客地址 参考

JavaScript RegExp 对象
深入浅出的javascript的正则表达式学习教程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81046.html

相关文章

  • 正则达式

    摘要:本文内容共正则表达式火拼系列正则表达式回溯法原理学习正则表达式,是需要懂点儿匹配原理的。正则表达式迷你书问世了让帮你生成和解析参数字符串最全正则表达式总结验证号手机号中文邮编身份证地址等是正则表达式的缩写,作用是对字符串执行模式匹配。 JS 的正则表达式 正则表达式 一种几乎可以在所有的程序设计语言里和所有的计算机平台上使用的文字处理工具。它可以用来查找特定的信息(搜索),也可以用来查...

    bang590 评论0 收藏0
  • javascript中的正则达式

    摘要:一概要正则表达式用途广泛,操作方便,执行效率高,是学习必须掌握的部分。关于正则表达式的详细内容,可以参考正则表达式必知必会或者百度搜索。匹配前面的子表达式零次或多次。和均为非负整数,其中。正则表达式中可以使用编码。 一:概要 正则表达式用途广泛,操作方便,执行效率高,是学习javascript必须掌握的部分。本章节主要讲正则表达式中的一些规则和几个用法,为下一章节的表单验证打下基础。关...

    MageekChiu 评论0 收藏0
  • 开发必会的vim命令技巧总结

    摘要:工作中常用到的快捷键命令模式下操作行光标处缩进,普通模式下向右缩进总结以上就是我认为作为开发会经常用到的操作,多联系就可以熟练掌握啦 vim起源 showImg(https://segmentfault.com/img/remote/1460000016742520); 上图可以清晰的看到早期的vim作者使用的机器,此时的终端机键盘是没有独立上下左右键位的,所以在vim的设计之初,HJ...

    dongfangyiyu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<