Skip to content

JavaScript 正则表达式 #24

@Calerme

Description

@Calerme

正则表达式图形化

REGEXPER

创建方法

字面量:

var reg = /\bis\b/g;

构造函数:

var reg = new RegExp('\\bis\\b', 'g');

修饰符

  • g
  • y
  • i
  • m 多行搜索

多行匹配:

`@123
@456
@789`.replace(/^@./g, 'x'); // 只有 @1 可以被匹配到

`@123
@456
@789`.replace(/^@./gm, 'x'); // @1 @4 @7 都可以被匹配到

基本字符类型

正则表达式由两种基本的字符类型组成:

  • 原义文本字符
  • 元字符 . * + ? $ ^ | \ () {} []

字符类

  • [abc]
  • [^abc]
var reg = /[abc]/; // 匹配 abc 中任意一个字符
// 取反
var reg = /[^abc]/; // 匹配非 abc 中的字符

范围类

  • [a-z] 闭合区间,包括 a 和 z 本身
  • [a-zA-Z]

预定义类

符号 作用
. 除回车换行外的所有字符
\d 数字字符 === [0-9]
\D 非数字字符 === [^0-9]
\s 匹配一个空白字符
\S 匹配一个非空白字符
\w 单词字符(字母、数字、下划线) === [a-zA-Z_0-9]
\W 非单词字符 === [^a-zA-Z_0-9]
\b 单词边界 便:\bis\b
\B 非单词边界
^ 以……开始
$ 以……结束

量词

符号 含义
? 0 次或 1 次(最多 1 次)
  • | 1 次 或多次(最少 1 次)
  • | 0 次或任意次
    {n} | n 次
    {n,m} | n~m 次
    {n,} | 至少出现 n 次

贪婪模式

尽可能多地匹配。默认为贪婪模式。

'12345678'.replace(/\d{3,6}/, 'x'); // -> 'x78'

非贪婪模式

尽可能少得匹配。使用在量词后加 ? 号表示。

'12345678'.replace(/\d{3,6}?/, 'x'); // -> 'x45678'

分组

作用:

  • 限定量词作用的范围
  • 配合 “或” 符号
  • 分组的反向引用(分组捕获)
/javascript{3}/ // t 重复 3 次
/(javascript){3}/ // javascript 重复 3 次

分组捕获:

示例,年月日 -> 月日年

'2017-01-01'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2-$3-$1');

忽略分组:

在分组前添加 ?:

'2017-01-01'.replace(/(?:\d{4})-(?:\d{2})-(\d{2})/, '$1-$2-$3'); // $1 匹配第三个分组,$2 $3 没有匹配值

前瞻后顾

前瞻

  • 正则表达式从文本头部向尾部开始解析,文本尾部方向称为前

  • 前瞻就是在匹配到规则的时候,向前检查是否符合断言,后顾/后瞻方向相反

  • 符合和不符合特定断言称为肯定/正向匹配和否定/负向匹配

  • 正向前瞻 exp(?=assert)

  • 负向前瞻 exp(?!assert)

示例:

// 断言,匹配项后边必须有一个数字
'a2*3'.replace(/\w(?=\d)/g, 'x'); // -> "x2*3"
'a2*34vv'.replace(/\w(?=\d)/g, 'x'); // -> "x2*x4vv'

// 断言,匹配项后边必须不是一个数字
'a2*34vv'.replace(/\w(?!\d)/g, 'x'); // -> "ax*3xxx"

后顾

  • ES6 开始支持后顾
  • (?<=assert)exp
  • (?<!assert)exp

正则对象实例上的属性

  • global
  • ignoreCase
  • multiline
  • lastIndex 如果正则拥有 g/y 修饰符,该值将被记为下一次搜索的位置,直至找不到时重置为 0。非全局模式该值永远是 0。
  • source 正则表达式的文本字符串

正则表达式实例上的方法

  • RegExp.prototype.test()
  • RegExp.prototype.exec()

RegExp.prototype.test() 返回一个布尔值,表示参数字符串中是否存在匹配正则的字符串。==当正则为全局模式时,每次调用 test 都会从正则的 lastIndex 开始向后查找==:

/abc/.test('abcdefg'); // -> true

**RegExp.prototype.exec()**没有匹配到值返回 null,匹配到返回一个结果数组,该数组的第一个值为匹配到的值,之后紧跟着的为匹配到的分组值:

  • result[0] - 匹配到的结果
  • result[1] - 分组 1
  • result[2] - 分组 2
  • result[3] - 分组 3
  • result[n] - 分组 n

该数组还有两个值,分别为:

  • result.index - 匹配到字符串的开始索引
  • result.input - 返回被匹配的整个字符串

字符串对象实例与正则相关的方法

  • String.prototype.search()
  • String.prototype.match()
  • String.prototype.split()
  • String.prototype.replace()

**String.prototype.search()**返回每一个匹配到 index,查不到返回 -1,该方法不支持全局匹配,忽略 g 修饰符。

String.prototype.match(),返回的值基本与 RegExp.prototype.exec() 返回的值相同。不同的是如果正则是全局模式,它返回的数组包括所有的匹配项,而 exec() 需要循环调用自身查找所有匹配项。

String.prototype.split(),以匹配到的字符分割字符串。

String.prototype.replace(reg, function (匹配到的字符串, 分组1, 分组2, ..., index, 原字符串) { return newStr; })

'abcdefg'.replace(reg, function (匹配到的字符串, 分组1, 分组2, ..., index, 原字符串) { 
    return newStr; 
});

其实以上方法的参数即使传入的是字符串,JavaScript 也会将它们转换为正则表达式。

一些示例

// 匹配以 jpg 结尾的 URL 地址
/http:\/\/.+\.jpg/

// 匹配 YYYY/MM/DD 或 YYYY-MM-DD 格式
/\d{4}[/-]\d{2}[/-]\d{2}/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions