上一篇文章中我们讲了正则表达式的基本用法,接下来博主想聊聊其中的细节,今天就从正则修饰符开始吧。

正则修饰符又称为正则标记(flags),它会对正则的匹配规则做限定,进而影响匹配的最终结果。在上次的文章中我们也提到过,正则修饰符一共有以下几种,可以单独使用,也可以组合使用:

/\w+/g; // global search
/\w+/i; // ignore case
/\w+/m; // multi-line
/\w+/u; // unicode
/\w+/y; // sticky /\w+/gi;
new RegExp('\\w+', 'gi');

其中的i好理解,正如上面的注释一样,ignore case或case insensitive,忽略大小写。

下面是一个简单的例子,正则表达式加上了i修饰符之后也可以匹配到大写字母:

'Hello World'.match(/hello/i);  // ["Hello"]

/hello/i.exec('Hello World');   // ["Hello"]

再来看看全局匹配修饰符g,下面是一个全局匹配的例子:

var source = 'hello world hello JS';

source.match(/hello/);      // ["hello"]

source.match(/hello/g);     // ["hello", "hello"]

从上面代码中可以看出,普通正则的匹配结果只有一个,如果想要找出全部的匹配结果,后面则需要加一个g修饰符,使其成为全局匹配模式。

全局修饰符g通常也会和多行匹配修饰符m结合使用,我们将上面例子稍加改动,添加一个换行符,正则也稍加修改:

var source = 'hello world\nhello JS';

source.match(/^hello.+/g);    // ["hello world"]

大家会看到,我们是要在多行文本中匹配以"hello"开头的字符串,但结果只出现了第一个匹配项,后面的"hello JS"并未匹配到,这时我们需要加入多行匹配修饰符m:

var source = 'hello world\nhello JS';

source.match(/^hello.+/gm);   // ["hello world", "hello JS"]

现在,所有的结果都匹配到了。

但需要注意的是,单独使用修饰符m是不起作用的,它必须和g相结合,就像下面例子一样,虽然有m修饰符,但仍旧只匹配到了第一行文字:

var source = 'hello world\nhello JS';

source.match(/^hello.+/m);    // ["hello world"]

另外,还有一个很重要的条件,那就是,只有正则中包含起始标记"^"或结束标记"$"时,修饰符m才会发挥它的作用,否则g不需要m,且看下面例子:

// 只有匹配开始标记^或结束标记$时,g才需要m

var source = 'hello world\nhey world';

// 正则中没有^或$ 只需g即可匹配多行
source.match(/he.+/g); // ["hello world", "hey world"] // 正则中含有^或$ g只能匹配第一个结果
source.match(/^he.+/g); // ["hello world"]
source.match(/.+world$/g); // ["hey world"] // 含有^或$的情况下 需要添加m 才可以匹配多行
source.match(/^he.+/gm); // ["hello world", "hey world"]
source.match(/.+world$/gm); // ["hello world", "hey world"]

以上介绍的都是正则修饰符在String#match()方法中的表现,我们也知道,RegExp#exec()是与之对应的一个方法,同样可以匹配字符串,返回结果数组,那么这个exec()方法对于含有全局修饰符的正则又会有什么样的表现呢?实际操作发现,RegExp#exec()方法与上面String#match()的规则大致相同,但不同的是,RegExp#exec()方法每次只会匹配一个结果,所以需多次环执行才能获取全部。我们来看下面示例:

var regex = /^hello.+/gm;
var source = 'hello world\nhello JS'; regex.exec(source); // ["hello world"]
regex.exec(source); // ["hello JS"]

可以看到每一次执行正则实例的exec()方法都会返回一个结果数组,由于正则中含有起始标记^和gm组合,我们需要执行两次才能获取到全部的结果,这是与String#match()方法不同的地方。一般来说,我们可以使用循环结构调用RegExp#exec()方法来获取所有的结果:

var result = null;
while (result = regex.exec(source)) {
console.log(result);
}
// output:
// ["hello world"]
// ["hello JS"]

对于RegExp#test()方法,一般是用来检测字符串是否匹配某种模式,如果要在多行中检测任意一行是否匹配时,同样需要gm组合,下面代码先简单检测匹配情况,然后在多行中进行匹配:

var source = 'hello world\nhey JS';

/^hello.+/.test(source);      // true

/^hey.+/.test(source);        // false
/^hey.+/g.test(source); // false /^hey.+/gm.test(source); // true

从结果来看,不加gm修饰符的正则,只能检测一行数据的匹配情况,加入gm后可以对多行进行检测,只要任意一行符合条件,即返回true。

最后再来说说String#replace()方法,同样地,如果正则中出现了^或$,那就需要加上gm组合,下面代码演示了多行替换的操作:

var source = 'hello world\nhello JS';

// 正则中没有^或$,全局g轻松搞定
source.replace(/hello/g, 'hey'); // "hey world\nhey JS" // 正则中含有^或$,全局g也无能为力,仅能替换第一行
source.replace(/^hello/g, 'hey'); // "hey world\nhello JS" // 需要使用gm组合
source.replace(/^hello/gm, 'hey'); // "hey world\nhey JS"

上面是全局匹配g和多行匹配m,下面介绍一下u修饰符。

u修饰符是ES6新增特性,可以启用Unicode模式对字符串进行正则匹配,能正确处理四个字节的UTF-16字符集。为什么需要这个修饰符呢,我们先来看一个例子:

/^.{3}$/.test('你好啊');    // true
/^.{3}$/.test('

JavaScript: 详解正则表达式之二的更多相关文章

  1. JavaScript系列文章:详解正则表达式之二

    在上一篇文章中我们讲了正则表达式的基本用法,接下来博主想聊聊其中的细节,今天就从正则修饰符开始吧. 正则修饰符又称为正则标记(flags),它会对正则的匹配规则做限定,进而影响匹配的最终结果.在上次的 ...

  2. JavaScript: 详解正则表达式之三

    在上两篇文章中博主介绍了JavaScript中的正则常用方法和正则修饰符,今天准备聊一聊元字符和高级匹配的相关内容. 首先说说元字符,想必大家也都比较熟悉了,JS中的元字符有以下几种: / \ | . ...

  3. JavaScript: 详解正则表达式之一

    正则表达式是一个精巧的利器,经常用来在字符串中查找和替换,JavaScript语言参照Perl,也提供了正则表达式相关模块,开发当中非常实用,在一些类库或是框架中,比如jQuery,就存在大量的正则表 ...

  4. JavaScript学习笔记-实例详解-类(二)

    实例详解-类(二)   //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...

  5. Android开发:文本控件详解——TextView(二)文字跑马灯效果实现

    一.需要使用的属性: 1.android:ellipsize 作用:若文字过长,控制该控件如何显示. 对于同样的文字“Android开发:文本控件详解——TextView(二)文字跑马灯效果实现”,不 ...

  6. Day03 javascript详解

    day03 js 详解 JavaScript的基础 JavaScript的变量 JavaScript的数据类型 JavaScript的语句 JavaScript的数组 JavaScript的函数 Ja ...

  7. dom对象详解--document对象(二)

       dom对象详解--style对象 style对象 style对象和document对象下的集合对象styleSheets有关系,styleSheets是文档中所有style对象的集合,这里讲解的 ...

  8. 【Java入门提高篇】Day30 Java容器类详解(十二)TreeMap详解

    今天来看看Map家族的另一名大将——TreeMap.前面已经介绍过Map家族的两名大将,分别是HashMap,LinkedHashMap.HashMap可以高效查找和存储元素,LinkedHashMa ...

  9. CocoaPods详解之(二)----进阶篇

    CocoaPods详解之----进阶篇 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/19178709 转载请注明出处 ...

随机推荐

  1. LiveCD 修复Grub引导

    /usr/sbin/grub-probe: error: failed to get canonical path of /cow 如果你是从这句报错search过来的,恭喜您!看来你也是一个调皮的孩 ...

  2. MongoDB开发深入之三:复制

    复制是基于操作日志oplog,相当于MySQL中的二进制日志,只记录发生改变的记录,复制是将主节点的oplog日志同步并应用到其他从节点的过程. 首先要理解两个概念:1.复制:提供冗余和高可用性:2. ...

  3. 【翻译】Flink Table Api & SQL — Hive —— 读写 Hive 表

    本文翻译自官网:Reading & Writing Hive Tables  https://ci.apache.org/projects/flink/flink-docs-release-1 ...

  4. [线性代数xOI/ACM]系数矩阵的QGXZ分解

    一些无关紧要的Q&A Q:你是怎么想到这个花里胡哨的算法的啊? A:前几天学习线性代数时有幸和Magolor大佬讨论到 $LU$ 分解在多解时的时间复杂度问题,于是yy出了这个奇怪(?)的算法 ...

  5. Centos7中rc.local设置springboot项目开机自启动

    在Centos7下,rc.local文件,开机默认是不执行的 1.进入rc.local中 路径如下图

  6. ThreadLocal源代码2

    private static int nextIndex(int i, int len) { return ((i + 1 < len) ? i + 1 : 0); } private stat ...

  7. Hadoop 3.1.2 + Hive 3.1.1

    一.安装Hadoop 1.1 版本说明 hadoop:3.1.2hive:3.1.1mysql:5.6.40 1.2 主机映射 添加IP与主机名的映射关系,在/etc/hosts文件里添加如下内容(所 ...

  8. SQL Server MERGE(合并)语句

    如何使用SQL Server MERGE语句基于与另一个表匹配的值来更新表中的数据.  SQL Server MERGE语句 假设有两个表,分别称为源表和目标表,并且需要根据与源表匹配的值来更新目标表 ...

  9. java字符串截取

    import org.apache.commons.lang.StringUtils; public class substr{ public static void main(String[] ar ...

  10. sqlserver 数据类型 C# clr 数据类型 映射

    https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql/linq/sql-clr-type-mapping#default- ...