@Dale-Lin
2022-07-29T17:28:10.000000Z
字数 4821
阅读 709
JavaScript
Regular Expression(正则表达式):使用单个字符串来描述,匹配一系列符合某语法规则的字符串。简单来说就是按某种规则去匹配符合条件的字符串。
在线测试工具:REGEXPER
字面量语法:
var reg = / expression / flags;
构造函数:
var rag = new RegExp( 'expression' , 'falgs' );
注意,在这里的表达式中传入的特殊字符要转义(包括转义符 )
元字符:
字符 | 含义 |
---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | 与X对应的控制字符(此表示Ctrl+X) |
[\u4e00-\u9fa5\uf900-\ufa2d] | 中文字符 |
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符(\x0B 是垂直制表符) |
\S | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符(字母、数字、下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
\w
也包括\d
Boundaries
Character | Meaning |
---|---|
^ | Match beginning of input. If the multiline flag is set to true, also matches immediately after a line break character. |
$ | Matches end of input. If the multiline flag is set to true, also matches immediately after a line break character. |
\b | Matches a word boundary. This is the position where a word character is not followed or preceded by another word-character, such as between a letter and a space. |
\B | Matches a non-word boundary. This is a position where the previous and next character are of the same type: Either both must be words, or both must be non-words. Such as between two letters or between two spaces. |
量词
字符 | 含义 |
---|---|
? | 出现零次或一次(最多出现一次) |
+ | 出现一次或多次(至少出现一次) |
* | 出现零次或多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
例如:
\d{2} 表示连续出现两次数字
\d{0,10} 表示最多连续出现十次数字
量词的贪婪与非贪婪模式
默认情况下,正则表达式匹配时会尽可能多地匹配字符串 (贪婪模式)。
在 量词(包括 *
+
?
{}
) 后面加上 ? 即可让正则表达式匹配尽量少的字符串 (非贪婪模式)。
分组:
使用 () 可以达到分组的功能,使量词作用于分组。(否则量词只作用于前一个字符)
规定没有匹配项的分组在exec()
结果数组中用undefined
表示。
或
可以使用 | 达到 或 的效果
忽略分组
不希望捕获某些分组,只需要在分组内加上?: 就可以。
例如:
(?:Byron).(ok)
这样就忽略了第一个分组,只捕获了 "ok" ,并作为 $1。
在表达式内使用 (?=assert)
(?!assert)
(?<=assert)
(?<!assert)
(不会作为匹配结果,只作为判断)
名称 | 正则 |
---|---|
正前瞻(positive lookahead) | exp(?=assert) |
负前瞻(negative lookahead) | exp(?!assert) |
正后顾 | exp(?<=assert) |
负后顾 | exp(?<!assert) |
例:
"a2*3".replace(/\w(?=\d)/g,"X"); //"X2*3"
"a2*35m0".replace(/\w(?=\d)/g,"X"); //"X2*X5X0"
"a2*35mm".replace(/\w(?!\d)/g,"X"); //"aX*3XXX"
对象属性
正则表达式方法
test():用于测试字符串参数中是否存在匹配正则表达式模式的字符串,存在则返回true,否则返回false。
语法
regexObj.test(str)
执行时注意全局模式下 lastIndex 的更新,在匹配完最后一个后的下一次执行会返回false。
var text = "000-00-0000"
var pattern = /\d{3}-\d{2}-\d{4}/ ;
if(pattern.test(text)){
console.log("The pattern was matched.");
}
在只想检查字符串是否和某模式匹配,而不需要知道其文本内容时(如上例可用在验证用户输入的情况),test() 方法常被用在 if 语句中。
主要方法: exec()
exec()
使用正则表达式模式对字符串执行搜索,全局模式下将更新lastIndex,以反映匹配结果。
若没匹配到文本则返回 null,否则返回一个包含数组的结果。
这个结果可视为一个数组;但当访问该结果的index
,input
属性时,表示匹配字符在原字符串中的索引、原字符内容。
语法
regexObj.exec(str)
返回数组:
1. 与正则表达式相匹配的文本
2. 与RegExp对象的第一个子表达式(分组)相匹配的文本(如果有的话)
3. 与RegExp对象的第二个子表达式(分组)相匹配的文本(如果有的话),以此类推
若非全局调用,则忽略 lastIndex 标志,可用于只找第一个匹配结果。
若设置了全局标志,则每次调用会从上一次的结尾后查找新匹配项,但仍然在找到一个(新)匹配项后停止并返回该项。而且 lastIndex 值会增加。
//Match "quick brown" followed by "jumps", ignoring characters in between.
var re = /quick\s(brown).+?=(jumps)/ig;
var result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog");
这个程序的返回值如下表:
对象 | 属性/索引 | 描述 | 例子 |
---|---|---|---|
result | [0] | 匹配的全部字符串 | Quick Brown Fox Jumps |
[1],...[n] | 括号中的分组捕获 | [1] = Brown [2] = Jumps |
|
index | 匹配到的字符位于原始字符串的索引值 | 4 | |
input | 原始字符串 | The Quick Brown Fox Jumps Over The Lazy Dog | |
re | lastIndex | 下次匹配开始的位置 | 25 |
ignoreCase | 是否使用'i'忽略大小写 | true | |
global | 是否使用'g'全局匹配 | true | |
multiline | 是否使用'm'进行多行匹配 | false | |
source | 正则匹配的字符串 | quick\s(brown).+?(jumps) |
var re = /(\w{4}?)\s(\w+)(?=\s) /;
var str = "Some text here waiting for testing.";
if(re.test(str)){
var result = re.exec(str);
console.log(result);
console.log(result[2]);
console.log(result.input);
console.log(result.length);
}
使用 ?<name>
命名捕获组:
const reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<date>[0-9]{2})/,
match = reDate.exec('2018-04-30');
使用 matchResult.groups[name]
使用分组:
match.groups.year; // 2018
match.groups.month; // 04
match.groups.date; // 30
在 String.replace()
中使用 $<name>
:
date.replace(reDate, '$<month>-$<date>-$<year>');
// "04-06-2019"
正则表达式的 valueOf() 方法返回正则表达式本身。
search()
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。若有,返回第一个匹配结果的首位的index,否则返回-1。
忽略g标识,不执行全局匹配,并且总是从字符串的开始进行检索。
在传入的参数不是正则表达式时,search方法会尝试把参数转换成正则表达式的形式。
match()
检索字符串,以检索一个或多个与regexp匹配的文本。
regexp是否具有标志g对结果影响很大。
非全局调用
match()方法只在字符串中执行一次匹配。
若没有找到任何匹配的文本,将返回null。
否则将返回一个数组,其中存放了与它找到的匹配文本有关的信息。数组的第一个元素存放匹配到的文本,而其余元素存放的是与regexp的子表达式(分组)匹配的文本。除了常规的数组元素之外,返回的数组还含有2个对象属性:
全局调用
match()方法将执行全局搜索,找到字符串中所有匹配的字符串。
若没找到匹配的字符串,将返回null。
若找到了一个或多个匹配的字符串,则返回一个数组。存放的是字符串中所有的匹配子串,且没有index属性或input属性。(此处 lastIndex 属性不起作用,为0)
split()
将字符串分割成字符的数组:
语法
str.split(separator, limit)
separator指定拆分发生的字符串:
"a,b,c,d".split(','); //["a","b","c","d"]
//使用第二个参数限制数组大小
var arr = "a,b,c,d";
arr.split(',', 2); //["a","b"]
//当分隔符出现在字符串头或尾时,返回数组的第一项或无限制的最后一项将是空白字符
arr.split(/[^\,]+/); //["", ",", ",", ",", ""]
在一些复杂的分割情况下可以使用正则表达式:
"a1b2c3d".split(/\d/); //["a","b","c","d"]
在执行时会尝试将参数转化成正则表达式的形式。
如果在str中不含separator,则返回一个含原字符串的数组。
若separator使用空字符串""
,则返回由每个字符组成的数组。
replace()
语法
str.replace(regexp|substr, newSubstr|function)
接收两个参数,第一个是要被替换的字符串或某种正则模式;第二个是替换后的字符串,也可以是一个每次匹配都要调用的函数,即可用function的返回值来作为替换后的动态字符。
若使用函数进行替换,该函数的参数为:
变量名 | 代表的值 |
---|---|
match | 匹配的字串 |
p1,p2... | 捕获某个分组 |
offset | 匹配到的子字符串在原字符串中的偏移量 |
string | 被匹配的原字符串 |
"a1b2c3d4e5".replace(/(\d)(\w)(\d)/g, function (match,p1,p2,p3,offset,string){
console.log(match);
return p1+p2;
}) //'1b2','3d4','a12c34e5'
在执行时会尝试将参数转化成正则表达式的形式。
第一个参数是正则表达式,第二个参数是字符串时,可以使用一些字符序列将正则表达式捕捉到的内容。