huabingtao / front-knowledge

基于Issues系统学习前端技术
0 stars 0 forks source link

正则表达式 #64

Open huabingtao opened 4 years ago

huabingtao commented 4 years ago

JavaScript 正则表达式

正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。本章介绍 JavaScript 正则表达式。

创建一个正则表达式

使用字面量的方式

var re = /ab+c/;

使用构造函数

var re = /ab+c/;

在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。

编写一个正则表达式的模式

简单模式

简单模式是由你想直接找到的字符构成。

var pattern = /abc/

特殊字符

断言

断言的组成之一是边界。对于文本、词或模式,边界可以用来表明它们的起始或终止部分(如向前断言,向后断言以及条件表达式)。 边界类断言 字符 含义
^ 匹配输入的开头。比如 /^A/ 匹配大写A开头的单词
$ 匹配输入的结束。比如 /t$/ 匹配字符串 'test foot'中的foot
\b 匹配一个单词的边界,这是一个字的字符前后没有另一个字的字符位置, 例如在字母和空格之间。例如: /\bm/ 在 "moon" 中匹配到 "m"
\B 匹配非单词边界。这是上一个字符和下一个字符属于同一类型的位置:要么两者都必须是单词,要么两者都必须是非单词,例如在两个字母之间或两个空格之间。字符串的开头和结尾被视为非单词。
其他断言 字符 含义
x(?=y) 向前断言: x 被 y 跟随时匹配 x。
x(?!y) 向前否定断言: x 没有被 y 紧随时匹配 x。
(?<=y)x 向后断言: x 跟随 y的情况匹配 y
(?!y)x 向后否定断言: x不跟随y时匹配x

字符类

字符类可以区分各种字符,例如区分字母和数子,空格和换行符。 类型 字符 含义
. 匹配除行终止符之外的任何单个字符: \n, \r, \u2028 or \u2029. 在字符集内,点失去了它的特殊意义,并与文字点匹配。
\d 匹配任何数字(阿拉伯数字)。 相当于 [0-9].
\D 匹配任何非数字(阿拉伯数字)的字符。相当于[^0-9].
\w 匹配基本拉丁字母中的任何字母数字字符,包括下划线。相当于 [A-Za-z0-9_].
\W 匹配任何不是来自基本拉丁字母的单词字符。相当于 [^A-Za-z0-9_].
\s 匹配单个空格字符,包括空格,制表符,换页符,换行符和其他Unicode空格。
\S 匹配空格以外的单个字符。
\t 匹配回车符。
\n 匹配换行符。
\ 1. 对于通常按字面意义处理的字符,表示下一个字符是特殊字符,不应按字面意义进行解释。例如,/b/匹配字符“ b”。通过在“ b”前面放置反斜杠,即使用/\b/,字符变得特殊以表示与单词边界匹配。2. 对于通常被特殊对待的字符,表示下一个字符不是特殊字符,应按字面解释。例如,“ ”是一个特殊字符,表示应该匹配0个或多个出现的前一个字符;例如,/a/表示匹配0或多个“ a”。要从字面上进行匹配,请在其前面加上反斜杠;例如,/a*/匹配“ a ”。

组和范围

组和范围表示表达式字符的 组和范围 字符 含义
x y 匹配 "x" 或 "y" 任意一个字符。例如, /green red/ 在 "green apple" 里匹配 "green",且在 "red apple" 里匹配 "red" 。
[xyz][a-c] 字符集。 匹配任何一个包含的字符。您可以使用连字符来指定字符范围,但如果连字符显示为方括号中的第一个或最后一个字符,则它将被视为作为普通字符包含在字符集中的文字连字符。也可以在字符集中包含字符类。
[^xyz] 一个否定的或被补充的字符集。也就是说,它匹配任何没有包含在括号中的字符。
(x) 捕获组: 匹配x并记住匹配项。例如,/(foo)/匹配并记住“foo bar”中的“foo”
\n 其中n是一个正整数。对正则表达式中与n括号匹配的最后一个子字符串的反向引用(计算左括号)。例如,/apple(,)\sorange\1/ 匹配 “apple,orange,cherry,peach” 中的 "apple,orange,", 其中 \1 引用了 之前使用 () 捕获的 ,
(?x) 具名捕获组: 匹配"x"并将其存储在返回的匹配项的groups属性中,该属性位于指定的名称下。尖括号(< 和 >) 用于组名。
(?:x) 非捕获组: 匹配 “x”,但不记得匹配。不能从结果数组的元素中收回匹配的子字符串([1], ..., [n]) or from the predefined RegExp object's properties ($1, ..., $9).

量词

量词表示要匹配的字符或表达式的数量。 字符 含义
x* 将前面的项“x”匹配0次或更多次。
x+ 将前一项“x”匹配1次或更多次。等价于{1,}。
x? 将前面的项“x”匹配0或1次。
x{n} 其中“n”是一个正整数,与前一项“x”的n次匹配。
x{n,} 其中,“n”是一个正整数,与前一项“x”至少匹配“n”次。
x{n,m} 其中,“n”是0或一个正整数,“m”是一个正整数,而m > n至少与前一项“x”匹配,最多与“m”匹配。
x*? x+? x?? x{n}? x{n,}? x{n,m}? 默认情况下,像 * 和 + 这样的量词是“贪婪的”,这意味着它们试图匹配尽可能多的字符串。?量词后面的字符使量词“非贪婪”:意思是它一旦找到匹配就会停止

使用正则表达式

正则表达式可以被用于 RegExp 的 exec 和 test 方法以及 String 的 match、replace、search 和 split 方法。

exec

exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。 在设置了 global 或 sticky 标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex 属性中。

const regex1 = RegExp('foo*', 'g');
const str1 = 'table football, foosball';
let array1;

while ((array1 = regex1.exec(str1)) !== null) {
  console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);
  // expected output: "Found foo. Next starts at 9."
  // expected output: "Found foo. Next starts at 19."
}

test

test() 方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 true 或 false。

var regex = /foo/g;

// regex.lastIndex is at 0
regex.test('foo'); // true

// regex.lastIndex is now at 3
regex.test('foo'); // false

match

match() 方法检索返回一个字符串匹配正则表达式的的结果。

str.match(regexp)

参数 regexp 一个正则表达式对象。如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。如果你没有给出任何参数并直接使用match() 方法 ,你将会得到一 个包含空字符串的 Array :[""] 。 返回值 如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)。 在这种情况下,返回的项目将具有如下所述的其他属性。 match 使用 global 和 ignore case 标志。

var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);

console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']

matchAll

matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。 如果没有 /g 标志,matchAll 会抛出异常。 matchAll 的另外一个亮点是更好地获取捕获组。

var regexp = /t(e)(st(\d?))/g;
var str = 'test1test2';
let array = [...str.matchAll(regexp)];

search

search() 方法执行正则表达式和 String 对象之间的一个搜索匹配。 如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1。

var str = "hey JudE";
var re = /[A-Z]/g;
var re2 = /[.]/g;
console.log(str.search(re)); // 4

replace

replace() 方法返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串。模式可以是一个字符串或者一个正则表达式,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。 在进行全局的搜索替换时,正则表达式需包含 g 标志。

// 当替换值是一个函数的时候
function replacer(match, p1, p2, p3, offset, string) {
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString);  // abc - 12345 - #$*%

split

split() 方法使用指定的分隔符字符串或者正则表达式将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。

const str = 'The quick brown fox jumps over the lazy dog.';

const words = str.split(' ');
console.log(words[3]);
// expected output: "fox"