JavaScript正则表达式

340 阅读5分钟

符号

数字.字母等
符号 意义 []中使用
\d 数字 [0-9]
\D 非数字 [^0-9]
\s 空白符 [ \f\n\r\t\v]
\S 非空白符 [^ \f\n\r\t\v]
\w 字母和数字和下划线 [A-Za-z0-9_]
\W 非字母和数字和下划线 [^A-Za-z0-9_]
[\u4e00-\u9fa5] 中文
[\u4E00-\u9FA5A-Za-z0-9_] 中文、英文、数字包括下划线
定位符
符号 意义
\b 单词边界
\B 非单词边界
$ 结尾
^ 开头
代表类
符号 意义 正则使用(//g)
. 任意字符 .+(任意字符一个或者多个)
| 或者 a|b(a或者b都可以匹配到)
[] 范围类 [0-9](代表数字)
[^] 非范围类 [^0-9](非数字)
匹配使用的符号
符号 意义
/g 全局搜索
/i 区分大小写
/m 多行搜索

/[0-9]/gmi

非打印字符
符号 含义
\t 水平制表符
\v 垂直制表符
\n 换行符
\r 回车符
\f 换页符
限定符
符号 使用 含义
? \d? 数字0到1个
+ \d+ 数字一个或者多个
{1} \d{1} 数字1个
{1, 5} \d{1, 5} 数字1到5个
{n, } \d{n, } 数字至少出现一次
* \d* 0个或者任意一个
特殊字符
字符 说明
^ 匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "^"
$ 匹配输入字符串的结尾位置。要匹配 "$" 字符本身,请使用 "$"
( ) 标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "\(" 和 "\)"
[ ] 用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号,请使用 "\[" 和 "\]"
{ } 修饰匹配次数的符号。要匹配大括号,请使用 "\{" 和 "\}"
. 匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 "\."
? 修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身,请使用 "?"
+ 修饰匹配次数为至少 1 次。要匹配 "+" 字符本身,请使用 "\+"
* 修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身,请使用 "\*"
| 左右两边表达式之间 "或" 关系。匹配 "|" 本身,请使用 "\|"
断言
字符 含义
x(?=y) 先行断言: y紧跟x的情况下匹配x。例如,对于/Jack(?=Sprat)/,“Jack”在跟有“Sprat”的情况下才会得到匹配./Jack(?=Sprat)/ “Jack”后跟有“Sprat”或“Frost”的情况下才会得到匹配。不过, 匹配结果不包括“Sprat”或“Frost”。
x(?!y) 负向先行断言: x后无y紧随的情况下匹配x。例如,对于/\d+(?!\。)/,数字后没有跟随小数点的情况下才会得到匹配。对于/\d+(?!.)/.exec(3.141),“3”得到匹配,“141”则无。
(?<=y)x 后行断言: x紧随y的情况下匹配x。例如,对于/(?<=Jack)Sprat/,“Sprat”紧随“Jack”时才会得到匹配。对于/(?<=Jack)Sprat,“Sprat”在紧随“Jack”或“Tom”的情况下才会得到匹配。不过,匹配结果中不包括“Jack”或“Tom”。
(?<!y)x 负向后行断言: x不紧随y的情况下匹配x。例如,对于/(?<!-)\d+/,数字紧随-符号的情况下才会得到匹配。对于/(?<!-)\d+/.exec(3) ,“3”得到匹配。 而/(?<!-)\d+/.exec(-3)的结果无匹配,这是由于数字之前有-符号。

示例

先行断言

// JS Lookahead assertion x(?=y)

let regex = /First(?= test)/g;

console.log('First test'.match(regex)); // [ 'First' ]
console.log('First peach'.match(regex)); // null
console.log('This is a First test in a year.'.match(regex)); // [ 'First' ]
console.log('This is a First peach in a month.'.match(regex)); // null

负向先行断言

console.log(/\d+(?!\.)/g.exec('3.141')); // [ '141', index: 2, input: '3.141' ]

后行断言

let oranges = ['ripe orange A ', 'green orange B', 'ripe orange C',];

let ripe_oranges = oranges.filter( fruit => fruit.match(/(?<=ripe )orange/));
console.log(ripe_oranges); // [ 'ripe orange A ', 'ripe orange C' ]
?: 或者捕获符
// [00:00.000] 作曲 : 接个吻,开一枪
// [00:01] 作词 : 接个吻,开一枪/王东旭/Lambert

let time = elem.match(/\[(\d{2,}):(\d{2})(?:\.(\d{2,3}))?]/g)
console.log(time)
// [00:00.000]
// [00:01]

JavaScript 正则表达式

分组

正则中用()来表示分组$1,2n

replace中的分组
// ([a-z]\d){3} 3组
'a1b2c3d4'.replace(/([a-z]\d){3}/g, 'X')
// Xd4
match中的分组
var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);

console.log(found);

// logs [ 'see Chapter 3.4.5.1',
//        'Chapter 3.4.5.1',
//        '.1',
//        index: 22,
//        input: 'For more information, see Chapter 3.4.5.1' ]

$1,2n符号
'a1b2c3d4'.replace(/(a1)(b2).+/g, '$1$2')
// a1b2
// $1='a1' $2=b2
方法

示例

replace(替换)
const p = 'The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?';

const regex = /dog/gi;

console.log(p.replace(regex, 'ferret'));
// expected output: "The quick brown fox jumps over the lazy ferret. If the ferret reacted, was it really lazy?"

console.log(p.replace('dog', 'monkey'));
// expected output: "The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?"
match(多行返回数组)
var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);

console.log(found);

// logs [ 'see Chapter 3.4.5.1',
//        'Chapter 3.4.5.1',
//        '.1',
//        index: 22,
//        input: 'For more information, see Chapter 3.4.5.1' ]

// 'see Chapter 3.4.5.1' 是整个匹配。
// 'Chapter 3.4.5.1''(chapter \d+(\.\d)*)'捕获。
// '.1' 是被'(\.\d)'捕获的最后一个值。
// 'index' 属性(22) 是整个匹配从零开始的索引。
// 'input' 属性是被解析的原始字符串。

match多行搜索的时候分组会出现无法获取分组信息

let lrc = `[00:00.000] 作曲 : 接个吻,开一枪
            [00:01] 作词 : 接个吻,开一枪/王东旭/Lambert
            [00:05.260]编曲:接个吻,开一枪
            [00:11.570]早上光照在房间 穿上新衬衫
            [00:14.460]镜子里我又长高了些
            [00:16.960]和同学吃火锅然后开黑带妹
            [00:19.280]一起狼人杀不用上学就不累
            [00:21.630]发条祝福传给你 请你别忘记`
let res = lrc.match(/\[(.+)\]/gm)
console.log(res)
// 0: "[00:00.000]"
// 1: "[00:01]"
// 2: "[00:05.260]"
// 3: "[00:11.570]"
// 4: "[00:14.460]"
// 5: "[00:16.960]"
// 6: "[00:19.280]"
// 7: "[00:21.630]"]
matchAll(针对match多行搜索)

返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。

let lrc = `[00:00.000] 作曲 : 接个吻,开一枪
            [00:01] 作词 : 接个吻,开一枪/王东旭/Lambert
            [00:05.260]编曲:接个吻,开一枪
            [00:11.570]早上光照在房间 穿上新衬衫
            [00:14.460]镜子里我又长高了些
            [00:16.960]和同学吃火锅然后开黑带妹
            [00:19.280]一起狼人杀不用上学就不累
            [00:21.630]发条祝福传给你 请你别忘记`
let res = lrc.matchAll(/\[(.+)\]/gm)
console.log([...res])

// 0: (2) ["[00:00.000]", "00:00.000", index: 0, input: ..., groups: undefined]
// 1: (2) ["[00:01]", "00:01", index: 25, input:...
...
exec
var re = /quick\s(brown).+?(jumps)/ig;
var result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
// result log: 
/**
0: "Quick Brown Fox Jumps"
1: "Brown"
2: "Jumps"
groups: undefined
index: 4
input: "The Quick Brown Fox Jumps Over The Lazy Dog"
**/
test(返回 true 或 false)
let str = 'hello world!';
let result = /^hello/.test(str);
console.log(result); 
// true
search()

方法执行正则表达式和 String 对象之间的一个搜索匹配。

const paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';

// any character that is not a word character or whitespace
const regex = /[^\w\s]/g;

console.log(paragraph.search(regex));
// expected output: 43

console.log(paragraph[paragraph.search(regex)]);
// expected output: "."