资讯专栏INFORMATION COLUMN

Javascript正则表达式入门

joywek / 386人阅读

摘要:返回值一个新的对象,具有指定的模式和标志。参数作用正则表达式规定匹配的类型。如果未找到匹配,则返回值为。返回值请注意,无论是否是全局模式,都会把完整的细节添加到它返回的数组中。字符串或正则表达式,从该参数指定的地方分割。

前言

PS:2018/03/27 优化文章格式,新增部分测试代码
说起正则其实大家都会经常接触到,前端小到校验,大到插件随处可见,简单的方法也能实现需求,不过缺乏灵活性,一旦需要复杂化,没有什么比正则更加合适的技术了。这也算是程序员的一道槛了。
以下资料截图都来源于JavaScript RegExp 对象

new RegExp(pattern, attributes)

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

参数 作用
pattern 字符串,指定了正则表达式的模式或其他正则表达式。
attributes 修饰符。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。

返回值:
一个新的 RegExp 对象,具有指定的模式和标志。如果参数 pattern 是正则表达式而不是字符串,那么 RegExp() 构造函数将用与指定的 RegExp 相同的模式和标志创建一个新的 RegExp 对象。
如果不用 new 运算符,而将 RegExp() 作为函数调用,那么它的行为与用 new 运算符调用时一样,只是当 pattern 是正则表达式时,它只返回 pattern,而不再创建一个新的 RegExp 对象。

抛出:
SyntaxError - 如果 pattern 不是合法的正则表达式,或 attributes 含有 "g"、"i" 和 "m" 之外的字符,抛出该异常。
TypeError - 如果 pattern 是 RegExp 对象,但没有省略 attributes 参数,抛出该异常。

RegExp 对象方法 RegExpObject.compile(regexp,modifier)

用于在脚本执行过程中编译正则表达式,也可用于改变和重新编译正则表达式(将正则表达式编译为内部格式,从而更快地执行)。

参数 作用
regexp 正则表达式
modifier 规定匹配的类型。"g" 用于全局匹配,"i" 用于区分大小写,"gi" 用于全局区分大小写的匹配。

实际上compile就是个修改编译作用,不能直接用于匹配正则

var str1 = "Hello World",
  str2 = "Hello World",
  patt = /man/g;
//正常正则
console.time();
str1 = str1.replace(patt, "person");
console.timeEnd();
//编译后的正则
console.time();
patt.compile(patt);
str2 = str2.replace(patt, "person");
console.timeEnd();

// default: 2.818ms
// default: 0.096ms

性能提升还是挺明显的

RegExpObject.exec(string)

用于检索字符串中的正则表达式的匹配。

参数 作用
string 必需。要检索的字符串。

返回值: 返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
说明: 调用 RegExp 对象 r 的 test() 方法,并为它传递字符串 s,与这个表示式是等价的:r.exec(s) != null ---> r.test(s)
重要事项: 如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串,就必须手动地把 lastIndex 属性重置为 0。
返回值: 请注意,无论 RegExpObject 是否是全局模式,exec() 都会把完整的细节添加到它返回的数组中。这就是 exec() 与 match() 的不同之处,后者在全局模式下返回的信息要少得多。因此我们可以这么说,在循环中反复地调用 exec() 方法是唯一一种获得全局模式的完整模式匹配信息的方法。

var str = "Every man in the world! Every woman on earth!",
  patt = /man/g,
  result;

while ((result = patt.exec(str)) != null) {
  console.log(result);
  console.log(patt.lastIndex);
}

// [ "man",
//   index: 6,
//   input: "Every man in the world! Every woman on earth!",
//   groups: undefined ]
// 9
// [ "man",
//   index: 32,
//   input: "Every man in the world! Every woman on earth!",
//   groups: undefined ]
// 35


index 属性声明的是匹配文本的位置。input 属性则存放的是被检索的字符串 string。

RegExpObject.test(string)

用于检测一个字符串是否匹配某个模式.

参数 作用
string 必需。要检索的字符串。

返回值: 如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
说明: 调用 RegExp 对象 r 的 test() 方法,并为它传递字符串 s,与这个表示式是等价的:r.exec(s) != null ---> r.test(s)

var str = "Every man in the world! Every woman on earth!",
  patt = /man/g;

console.log(patt.test(str)); // true
支持正则表达式的 String 对象方法 stringObject.search(regexp)

用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。

参数 作用
regexp 该参数可以是需要在 stringObject 中检索的子串,也可以是需要检索的 RegExp 对象。

返回值: stringObject 中第一个与 regexp 相匹配的子串的起始位置,如果没有找到任何匹配的子串,则返回 -1。
说明: search() 方法不执行全局匹配,它将忽略标志 g。它同时忽略 regexp 的 lastIndex 属性,并且总是从字符串的开始进行检索,这意味着它总是返回 stringObject 的第一个匹配的位置。

var str = "How Are you doing today?How Are you doing today?"
console.log(str.search(/are/gi)); // 4
stringObject.match(searchvalue/regexp)

可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。

参数 作用
searchvalue 必需。规定要检索的字符串值。
regexp 必需。规定要匹配的模式的 RegExp 对象。如果该参数不是 RegExp 对象,则需要首先把它传递给 RegExp 构造函数,将其转换为 RegExp 对象。

返回值: 存放匹配结果的数组。该数组的内容依赖于 regexp 是否具有全局标志 g。
说明: match() 方法将检索字符串 stringObject,以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。
如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。除了这些常规的数组元素之外,返回的数组还含有两个对象属性。index 属性声明的是匹配文本的起始字符在 stringObject 中的位置,input 属性声明的是对 stringObject 的引用。
如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到 stringObject 中的所有匹配子字符串。若没有找到任何匹配的子串,则返回 null。如果找到了一个或多个匹配子串,则返回一个数组。不过全局匹配返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。
注意: 在全局检索模式下,match() 即不提供与子表达式匹配的文本的信息,也不声明每个匹配子串的位置。如果您需要这些全局检索的信息,可以使用 RegExp.exec()。

var str = "How are you doing today?How are you doing today?"
console.log(str.match(/ a/));
console.log(str.match(/a.e/g));
// [ " a",
//   index: 3,
//   input: "How are you doing today?How are you doing today?",
//   groups: undefined ]
// [ "are", "are" ]
stringObject.replace(regexp/substr,replacement)

用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

参数 作用
regexp/substr 必需。规定子字符串或要替换的模式的 RegExp 对象。请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。
replacement 必需。一个字符串值。规定了替换文本或生成替换文本的函数。

返回值: 一个新的字符串,是用 replacement 替换了 regexp 的第一次匹配或所有匹配之后得到的。

var str = "How are you doing today?"
console.log(str.replace(/ /g, "|"));
console.log(str.replace(/ /g, function () {
  return "-----"
}));
console.log(str.replace(/a.e/g, "were"));

// How|are|you|doing|today?
// How-----are-----you-----doing-----today?
// How were you doing today?
stringObject.split(separator,howmany)

用于把一个字符串分割成字符串数组。

参数 作用
separator 必需。字符串或正则表达式,从该参数指定的地方分割 stringObject。
howmany 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。

返回值: 一个字符串数组。该数组是通过在 separator 指定的边界处将字符串 stringObject 分割成子串创建的。返回的数组中的字串不包括 separator 自身。

            但是,如果 separator 是包含子表达式的正则表达式,那么返回的数组中包括与这些子表达式匹配的字串(但不包括与整个正则表达式匹配的文本)。
var str = "How are you doing today?"
console.log(str.split(" ", 3));
console.log(str.split(" "));
console.log(str.split("are"));

// [ "How", "are", "you" ]
// [ "How", "are", "you", "doing", "today?" ]
// [ "How ", " you doing today?" ]
方括号用于查找某个范围内的字符:

var str = "abcdaabc164984616464646464AAWEGAWGAG";

console.log(str.match(/[a-f]/g).join(""));
console.log(str.match(/[A-F]/g).join(""));
console.log(str.match(/[A-z]/g).join(""));
console.log(str.match(/[0-9]/g).join(""));
console.log(str.match(/[adgk]/g).join(""));
console.log(str.match(/[^a-z]/g).join(""));
console.log(str.match(/(r|b|g)/g).join(""));

// abcdaabc
// AAEAA
// abcdaabcAAWEGAWGAG
// 164984616464646464
// adaa
// 164984616464646464AAWEGAWGAG
// bb
元字符(Metacharacter)是拥有特殊含义的字符:


首先看看通用并且简单的几个元字符.

var str = "Every man in the world! 1, 2, 3, Let"s go!!";

console.log(str.match(/m.n/g).join(""));
console.log(str.match(/w/g).join(""));
console.log(str.match(/W/g).join(""));
console.log(str.match(/d/g).join(""));
console.log(str.match(/D/g).join(""));
console.log(str.match(/s/g).join(""));
console.log(str.match(/S/g).join(""));

// man
// Everymanintheworld123Letsgo
//     ! , , , " !!
// 123
// Every man in the world! , , , Let"s go!!
         
// Everymanintheworld!1,2,3,Let"sgo!!

b 和 B元字符匹配单词边界与否意思是在单词边界匹配的位置,单词字符后面或前面不与另一个单词字符直接相邻。请注意,匹配的单词边界并不包含在匹配中。换句话说,匹配的单词边界的长度为零。(不要与 [b] 混淆。)

var str = "If you love yourself, you can jump into your life from a springboard of self-confidence. If you love yourself, you can say what you want to say, go where you want to go.";

console.log(str.match(/your/));//->里面的your
console.log(str.match(/yourB/));//->里面的yourself,yourself

// [ "your",
//   index: 40,
//   input: "If you love yourself, you can jump into your life from a springboard of self-confidence. If you love yourself, you can say what you want to say, go where you want to go.",
//   groups: undefined ]
// [ "your",
//   index: 12,
//   input: "If you love yourself, you can jump into your life from a springboard of self-confidence. If you love yourself, you can say what you want to say, go where you want to go.",
//   groups: undefined ]

进制数我没用,不太了解,下面都是指W

var str = "If you love yourself, you can jump into your life from a springboard of self-confidence. If you love yourself, you can say what you want to say, go where you want to go.";

console.log(str.match(/127/gi));//以八进制数 xxx 规定的字符。
console.log(str.match(/x57/gi));//以十六进制数 dd 规定的字符
console.log(str.match(/u0057/gi));//以十六进制数 xxxx 规定的 Unicode 字符。

其他就字面意思,不解释了.

量词

var str = "n, On, Oon, Ooon";

console.log(str.match(/o+n/gi));
console.log(str.match(/o*n/gi));
console.log(str.match(/o?n/gi));

console.log(str.match(/o{1}n/gi));
console.log(str.match(/o{1,2}n/gi));
console.log(str.match(/o{3,}n/gi));

console.log(str.match(/^n/gi));
console.log(str.match(/on$/gi));

console.log(str.match(/O(?=on)/));
console.log(str.match(/O(?!on)/));

// [ "On", "Oon", "Ooon" ]
// [ "n", "On", "Oon", "Ooon" ]
// [ "n", "On", "on", "on" ]
// [ "On", "on", "on" ]
// [ "On", "Oon", "oon" ]
// [ "Ooon" ]
// [ "n" ]
// [ "on" ]
// [ "O", index: 7, input: "n, On, Oon, Ooon", groups: undefined ]
// [ "O", index: 3, input: "n, On, Oon, Ooon", groups: undefined ]
捕获
参数 作用
(n) 匹配n,并捕获文本到自动命名的组里
(?:n) 匹配 n但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。

正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。 对一个正则表达式模式或部分模式两边添加圆括号()可以把这部分表达式存储到一个临时缓冲区中。所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容按顺序存储。 存储子匹配的缓冲区编号从1开始,连续编号至最大99个子表达式。 每个缓冲区都可以使用"n"(或用"$n")访问,其中n为1至99的阿拉伯数字,用来按顺序标识特定缓冲区(子表达式)。

var str = "I am the best of the best in the best place";
console.log(str.match(/(the best).*1/g)) //["the best of the best in the best"]

注意的是它只能匹配重复的规则

var str = "aa bb ab";
console.log(str.match(/(w)1/g))//["aa", "bb"]
console.log(str.match(/(?:w)1/g))//null

意思前面匹配到a后面只能也是a,哪怕它定制的规则的所有单词
下面是或的简短写法

var str = "better best";

console.log(str.match(/(better|best)/g));
console.log(str.match(/be(?:tter|st)/g));
贪婪与懒惰模式

贪婪模式,它会尽可能匹配多的字符
懒惰模式,它会尽可能匹配少的字符
写法区别就是贪婪模式后面加上?就变成懒惰模式了

var str = "

123

abc

"; console.log(str.match(/

S*

/)); // ["

123

abc

", index: 0, input: "

123

abc

"] console.log(str.match(/

S*?

/)); // ["

123

", index: 0, input: "

123

abc

"]

正则匹配还有很多强大的功能位,只讲到这里一半是因为水平有限,平常用到也就这些.另一半是在javascript里支持的功能也是有限,现阶段讲了也用不到就算了,

---------------------------------------------------实战篇-----------------------------------------------------------------------------

现在开始来写正题了.先写个简单的日期匹配练手,最基础的数字匹配

var str = "2017.04.10 2017-4-10 2017/04/1";

//基础写法
console.log(str.match(/[0-9]{4}(.|-|/)[0-9]{1,2}(.|-|/)[0-9]{1,2}/g));
//元字符写法
console.log(str.match(/d{4}.d{1,2}.d{1,2}/g));
//量词写法
console.log(str.match(/d{4}(.d+){2}/g));

// [ "2017.04.10", "2017-4-10", "2017/04/1" ]
// [ "2017.04.10", "2017-4-10", "2017/04/1" ]
// [ "2017.04.10", "2017-4-10", "2017/04/1" ]

常见的支付金额校验,纯数字大于0最多两个小数

var reg = /^(0|[1-9]d*)?(.d{1,2})?$/g;

console.log("023".match(reg));
console.log(".5".match(reg));
console.log("255".match(reg));
console.log("255.1".match(reg));
console.log("255.31".match(reg));
console.log("255.313".match(reg));

// null
// [ ".5" ]
// [ "255" ]
// [ "255.1" ]
// [ "255.31" ]
// null

这个有点复杂,折腾很久,在网上找到好多的答案其实都是错漏百出的,例如
/^d*.?d{0,2}$/: 它能匹配012这种不正常格式
/(^1-9?(.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9].0-9?$)/: 这种不用细看都知道不是合适答案,也就相当于分拆出每个可能,发挥不出正则的优势,我都没往下看了

逐步分析一下我自己写的:
[1-9]d*:开头衹能1-9,后面可不带或带多个数字
^(0|[1-9]d*)?: 或者0开头,也能省略开头
(.d{1,2})?$: 两个小数可要可不要

之前还遇到一个面试题是替换字符串内的变量,如下

var str = "Hello ${name},you are so ${praise}",
  obj = {
    name: "高圆圆",
    praise: "goodly"
  };

console.log(str.replace(/${([^{}]+)}/g, function (match, key) {
  return obj[key]
}))
// Hello 高圆圆,you are so goodly

---------------------------------------------------尾声-----------------------------------------------------------------------------
其实应该还有很多东西可以说,但是目前先熟悉掌握这些就够了,过段时间我有时间再继续写些进阶知识

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

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

相关文章

  • JS正则达式入门,看这篇就够了

    摘要:如果遇到非常的复杂的匹配,正则表达式的优势就更加明显了。关于正则表达式书写规则,可查看,上面说的很清楚了,我就不贴出来了。替换与正则表达式匹配的子串,并返回替换后的字符串。结语正则表达式并不难,懂了其中的套路之后,一切都变得简单了。 前言 在正文开始前,先说说正则表达式是什么,为什么要用正则表达式?正则表达式在我个人看来就是一个浏览器可以识别的规则,有了这个规则,浏览器就可以帮我们判断...

    wenzi 评论0 收藏0
  • 前端计划——JavaScript正则达式快速入门

    摘要:前言正则表达式时处理字符串中常用的手法,本文以简单的方式,快速展示了中正则相关的基础知识点。文末还提供了几个简单的正则相关面试题。接下来是正则部分,注意后面的并不匹配,也就是比如,实际匹配的值是和,在和后面加上,就完成了预期。 前言:正则表达式时处理字符串中常用的手法,本文以简单的方式,快速展示了JavaScript中正则相关的基础知识点。文末还提供了几个简单的正则相关面试题。个人总结...

    Xufc 评论0 收藏0
  • JavaScript正则达式-基础入门

    摘要:正则表达式基础入门字符类,如为匹配任何字符组成的字符重复如为匹配一到三个单词选择分组和引用指定匹配位置修饰符直接量字符可用于模式匹配的方法对象基本要素字符类方括号内的任意字符不在方括号内的任意字符除换行符和其他行终止符之外的任意字符任何字 JavaScript正则表达式-基础入门 字符类,如 /w/ 为匹配任何ASCII字符组成的字符 重复, 如 /w{1,3}/ 为匹配一到三个单词...

    Amos 评论0 收藏0
  • TRY REGEX:正则达式交互式入门教程 翻译&解答

    摘要:写一个正则表达式来测试变量中是否包含字符串。用函数给出不使用字符,但和等价的正则表达式。第十四课标志全局匹配标志第二个常用的标志是全局匹配标志,用字母表示。写出一个正则表达式来检验合法性。非捕获组的主要用途是给一个组赋予量词。 TRY REGEX 是一个交互式的正则表达式学习项目项目地址:https://github.com/callumacra...在线地址:http://tryre...

    李义 评论0 收藏0
  • 正则达式

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

    bang590 评论0 收藏0
  • 前端文档收集

    摘要:系列种优化页面加载速度的方法随笔分类中个最重要的技术点常用整理网页性能管理详解离线缓存简介系列编写高性能有趣的原生数组函数数据访问性能优化方案实现的大排序算法一怪对象常用方法函数收集数组的操作面向对象和原型继承中关键词的优雅解释浅谈系列 H5系列 10种优化页面加载速度的方法 随笔分类 - HTML5 HTML5中40个最重要的技术点 常用meta整理 网页性能管理详解 HTML5 ...

    jsbintask 评论0 收藏0

发表评论

0条评论

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