Javascript正则表达式小册

Javascript正则表达式小册

正则表达式,作为一个合格的开发人员来说,应该都会使用。But,在使用过程中,你真的能顺风顺水快速写出自己想要的正则表达式吗?我看不尽然,反正小编做不到,所以小编重新学习了一下javascript正则表达式的知识,并写了一篇粗略总结,分享给大家。

注意,本文通读预计需要10分钟以上。

正则表达式概念

正则表达式是由普通字符以及特殊字符组成的文字模式。所谓普通字符就是代表其本身含义的字符,例如字母a,b,数字1、2等。特殊字符指的是有特殊含义的非字母字符。例如\d代表数字0-9。

正则表达式作用

正则表达式能做的事情很多,比如:校验用户输入的手机号是不是合法,在IDE中对某些代码进行批量替换或查找,从url或者cookie中取出某个key对应的value等等。

正则表达式写法

1、字面量写法:

/正则表达式主体/修饰符(可选)

例:/\w/igm;

2、对象写法:

new RegExp('正则表达式主体', '修饰符(可选)')

例:new RegExp('\\w', 'igm')

正则表达式修饰符

* 修饰符:

* i: 忽略大小写

* g: 全局匹配

* m: 多行匹配

i和g比较好理解,m多行匹配由于有使用限制,导致应用场景可能并不多。

限制:只有当目标字符串含有\n,而且正则表达式中含有^或$的时候,m修饰符才有作用。

看下面的例子

例:

var str = "def\nabc";

var singleLineReg = /^abc/;

var multiLineReg = /^abc/m;

singleLineReg.test(str); // false

multiLineReg.test(str); // true

正则表达式中的字符

元字符

在正则表达式中有特殊含义的字符,有很多,比如\d,\w等。下面从字符类、字符类取反、范围类、预定义类、边界匹配、量词这几个分类来了解下元字符。

字符类

一般情况下,正则表达式一个字符对应字符串一个字符,但是有的时候,我们希望匹配不是某个字符,而是某类字符,就会用到字符类。

写法:[字符]

例:匹配字符a或者b中任意一个字符,把ab当成一类。

var reg = /[ab]/;

字符类取反

匹配不是某些字符,可以用字符类取反。

写法:[^字符]

例:匹配不是a或b的字符。

var reg = /[^ab]/;

范围类

有的时候我们需要匹配一个范围内的字符串,虽然可以穷举,但是更便捷的方法是使用范围类。

例:匹配3到8之间的数字

var reg = /[3-8]/;

匹配小写a到z和大写A到Z之间的英文字母

var reg = /[a-zA-Z]/;

预定义类

下表列出了常见的预定义类,大家需要熟练掌握。

可以看到大部分预定义类大小写书写方式所代表的含义正好相反,记忆起来很方便。

边界匹配符

正则表达式提供下如下边界匹配符

例:

1、把@全部替换为A。

var str = "@163.com@126.com";

var reg = /@/g;

str.replace(reg, "A"); // "A163.comA126.com"

2、把以@开头的字符串中的@全部替换为A。

var str = "@163.com@126.com";

var reg = /^@/g;

str.replace(reg, "A"); // "A163.com@126.com"

3、把"This is a apple, is it?"中的is替换为A。

var str = "This is a apple, is it?";

var reg1 = /is/g;

var reg2 = /\bis\b/g;

var reg3 = /\Bis\b/g;

str.replace(reg1, "A"); // "ThA A a apple, A it?"

str.replace(reg2, "A"); // "This A a apple, A it?"

str.replace(reg3, "A"); // "ThA is a apple, is it?"

可以看到,如果不加单词边界,This中的is也被替换了。左右都加上单词边界,完整的is单词都被替换了。左边加非单次边界,右边加单词边界,只有This中的is被替换了。

量词

假设有这样的场景,匹配字母a连续出现3次的场景。我们可以写成/aaa/,如果匹配a连续出现100次,穷举的写法显然不适合,我们应该使用量词。/a/这就表示连续出现3次a的情况。正则表达式支持下面的量词。

正则表达式贪婪与非贪婪模式

贪婪模式

所谓贪婪模式是指正则表达式会尽可能多的匹配字符串,看下面的例子。

例:

把连续出现2到4次的数字替换为字母A。

var reg = /\d/;

var str = "123456";

str.replace(reg, "A"); // "A56"

通过结果可以看到,1234全部被替换了。12,123,1234都满足数字2到4次,但是最终却是1234满足匹配结果并被替换掉了。这就是正则表达式的贪婪模式。

非贪婪模式

正则表达式默认支持贪婪模式,如果我们不希望正则表达式贪婪匹配,而是尽可能少的匹配,那么就需要开启非贪婪模式。只需要在量词后面加上?即可。

例:

var reg = /\d?/;

var str = "123456";

str.replace(reg, "A"); // "A3456"

可以看到只匹配并替换了12,这就是非贪婪模式。

正则表达式分组

分组

通俗来说,分组就是把某些字符用()括起来,小括号里面的内容就形成了一个分组。

例:匹配字符串abc连续出现三次。

var reg = /(abc)/;

如果不使用小括号,/abc/相当于c连续出现三次,而不是abc连续出现三次。

在javascript中用竖线|来代表或。

例:匹配字符串abc或者def连续出现三次。

var reg = /abc|def/;

注意,或两边的所有字符都是匹配范围,上面的正则表达式代表abc或def匹配,而不是紧邻竖线的c或f。如果只想匹配紧邻的c或者f怎么写呢?如下是正确的写法:

var reg = /ab(c|d)ef/;

注意:上面的正则匹配的是"abcef"或"abdef",而不是"abcdef"。

捕获分组

被正则捕获到的分组中的字符串会被暂存,并且从1开始编号,用$1,$2,$3...来代表分组匹配的内容,相当于js中的变量。

例:把年月日“2018-10-16”替换为月日年“10/16/2018”

var reg = /(\d)-(\d)-(\d)/;

var str = "2018-10-16";

str.replace(reg, "$2/$3/$1"); // "10/16/2018"

非捕获分组

需要分组但又不希望捕获这个分组,可以使用非捕获分组。在分组开头加入?:即可。

例:把月日年“2018-10-16”替换为月日“10/16”

var reg = /(?:\d)-(\d)-(\d)/;

var str = "2018-10-16";

str.replace(reg, "$2/$3"); // "16/$3"

str.replace(reg, "$1/$2"); // "10/16"

注意:非捕获分组会从捕获到的第一个分组开始为1编号,没有编号的会把编号变量作为本身字符串处理。这就是为什么第一次匹配结果为"16/$3"了。

正则表达式前瞻

前瞻也叫零宽断言,正则表达式在匹配到规则的时候,向前检查是否符合断言。其中前瞻又分为正向前瞻和负向前瞻。下面了解下什么是正向前瞻,什么是负向前瞻。

正向前瞻

写法:(?=表达式)

含义:想要匹配结果,并且这个结果后面一定要符合什么条件

例:找出所有jpg类型的图片的名字

var imgs = '12.jpg,34.png,56.jpg,78.gif';

var reg = /\w+(?=\.jpg)/g;

imgs.match(reg) // ["12", ",56"];

说明:match后面会讲到。

注意:断言部分并不算在匹配结果内,只是为了辅助找到匹配结果而设置的匹配条件而已。

负向前瞻

写法:(?!表达式)

含义:想要匹配的结果后面一定要不符合什么条件

例:匹配连续三个b,并且后面没有数字。

var str = 'bbb333,bbbbbabb,aabbbbbbbba';

var reg = /b(?!\d+)/g;

str.match(reg); // ["bbbbb", "bbbbbbbb"]

正则表达式方法

1、reg.test(str)

含义:用于测试某个字符串参数中是否存在匹配正则表达式模式的字符串。存在值为true,不存在值为false。

例:

/\d/.test('ab') // false

/\d/.test('123') // true

2、reg.exec(str)

含义:检索字符串中指定的值。返回找到的值,并确定其位置。匹配到返回数组,匹配不到返回null。此数组的第0个元素是与正则表达式相匹配的文本,第1个元素是与RegExpObject的第1个子表达式相匹配的文本(如果有的话),第2个元素是与RegExpObject的第2个子表达式相匹配的文本(如果有的话),以此类推。

除了数组元素和length属性之外,exec()方法还返回两个属性。index属性声明的是匹配文本的第一个字符的位置。input属性则存放的是被检索的字符串string。

例:

/Hello/g.exec('Hello world') // ["Hello", index: 0, input: "Hello world", groups: undefined]

字符串方法

1、string.replace(reg, value)

含义:替换与正则表达式匹配的子串,

例:

'ab'.replace(/a/, 'X') // 'Xb'

2、string.search(reg)

含义:用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。返回第一个匹配结果的index,找不到返回-1。

例:

'abcde'.search(/a/); // 0

'abcde'.search(/b/); // 1;

3、string.match(reg)

含义:用于检索字符串,以找到一个或多个匹配的文本。

说明:此方法分为全局调用和非全局调用。

如果 regexp 没有标志 g,那么 match() 方法就只能在 string中执行一次匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。除了这些常规的数组元素之外,返回的数组还含有两个对象属性。index 属性声明的是匹配文本的起始字符在 string中的位置,input 属性声明的是对 string的引用。

如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到 string中的所有匹配子字符串。若没有找到任何匹配的子串,则返回 null。如果找到了一个或多个匹配子串,则返回一个数组。不过全局匹配返回的数组的内容与前者大不相同,它的数组元素中存放的是string中所有的匹配子串,而且也没有 index 属性或 input 属性。

总结

javascript正则表达式看似简单,却并不简单,里面的知识点很多很杂,但是熟练掌握后能帮助我们处理一些很复杂的情景。大家并不需要刻意去记忆,只要常把正则拾起来用就会很熟练很扎实的掌握这门技术,小编也在不断尝试使用中。

另外,本文只是一篇入门级,总结概括性文章,文中观点及概念是小编总结概括出来的,难免会有遗漏或者错误,欢迎大家留言批评指正。在此感谢大家。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181018G1PQ5N00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券