文章目录
- 深入理解JavaScript正则表达式
-
- 1. 正则表达式基础
-
- 1.1 创建正则表达式
-
- 1.1.1 字面量语法
- 1.1.2 构造函数
- 1.2 匹配模式
-
- 1.2.1 全局模式(g)
- 1.2.2 不区分大小写模式(i)
- 1.2.3 多行模式(m)
- 总结
- 1.3 特殊字符和字符类
-
- 1.3.1 特殊字符和字符类
- 代码示例
- 总结
深入理解JavaScript正则表达式
正则表达式(Regular Expression,常简称为regex或regexp)是处理字符串的强大工具,它提供了一种灵活的方式来搜索、匹配(以及在某些情况下替换)文本中的子字符串。在JavaScript中,正则表达式是通过
1. 正则表达式基础
1.1 创建正则表达式
在JavaScript中,你可以通过两种方式创建正则表达式:
- 字面量语法:使用斜杠(/)包围的模式,如
/ab+c/ 。 - 构造函数:使用
new RegExp('ab+c') 。
1.1.1 字面量语法
字面量语法是创建正则表达式最直接的方式。你只需要将模式放在斜杠(/)之间即可。例如,如果你想匹配字符串中所有出现的“ab+c”模式(即一个“a”后面跟着一个或多个“b”,再后面是一个“c”),你可以这样写:
const regex = /ab+c/;
这个正则表达式可以用来测试字符串中是否存在符合该模式的子串:
const str = 'abc abbc abbbbbc'; const result = str.match(regex); console.log(result); // 输出: [ 'abc', index: 0, input: 'abc abbc abbbbbc', groups: undefined ]
注意,在这个例子中,
1.1.2 构造函数
另一种创建正则表达式的方式是使用
const pattern = 'ab+c'; const flags = 'i'; // 不区分大小写 const regex = new RegExp(pattern, flags);
这个正则表达式与之前的字面量语法创建的等价,但是它不区分大小写:
const str = 'aBc AbBc aBBBBc'; const result = str.match(regex); console.log(result); // 输出: [ 'aBc', index: 0, input: 'aBc AbBc aBBBBc', groups: undefined ]
在这个例子中,由于我们设置了“i”标志,所以正则表达式在匹配时忽略了大小写。因此,它能够匹配到“aBc”。
请注意,当使用构造函数创建正则表达式时,由于字符串中的反斜杠()是转义字符,你可能需要对它进行双重转义。例如,如果你想在构造函数中表示
const regex = new RegExp('\d');
或者,你可以使用原始字符串字面量(在ES6及更高版本中可用),这样就不需要对反斜杠进行转义:
const regex = new RegExp(`\d`); // 实际上不需要双重转义,但这里为了演示 // 或者更简洁地 const regex = /d/; // 直接使用字面量语法,通常更可取
在实际开发中,如果正则表达式的模式是固定的,推荐使用字面量语法,因为它的语法更简洁,性能也更好。如果模式需要根据运行时的情况动态生成,那么构造函数是一个更好的选择。
1.2 匹配模式
1.2.1 全局模式(g)
全局模式意味着正则表达式会搜索整个字符串以找到所有匹配项,而不仅仅是找到第一个匹配项就停止。如果没有使用全局模式,
代码示例:
const regexNonGlobal = /foo/; // 非全局模式 const regexGlobal = /foo/g; // 全局模式 const str = 'foo and foo'; const matchesNonGlobal = str.match(regexNonGlobal); const matchesGlobal = str.match(regexGlobal); console.log(matchesNonGlobal); // 输出: [ 'foo', index: 0, input: 'foo and foo', groups: undefined ] console.log(matchesGlobal); // 输出: [ 'foo', 'foo' ]
在这个例子中,非全局模式的正则表达式只匹配到了第一个“foo”,而全局模式的正则表达式匹配到了所有出现的“foo”。
1.2.2 不区分大小写模式(i)
不区分大小写模式使正则表达式在匹配时忽略字符的大小写。这意味着它会将大写和小写字符视为相同。
代码示例:
const regexCaseSensitive = /FOO/; // 区分大小写 const regexCaseInsensitive = /FOO/i; // 不区分大小写 const str = 'FOO and foo'; const matchesCaseSensitive = str.match(regexCaseSensitive); const matchesCaseInsensitive = str.match(regexCaseInsensitive); console.log(matchesCaseSensitive); // 输出: [ 'FOO', index: 0, input: 'FOO and foo', groups: undefined ] console.log(matchesCaseInsensitive); // 输出: [ 'FOO', 'foo' ]
在这个例子中,区分大小写的正则表达式只匹配到了大写的“FOO”,而不区分大小写的正则表达式匹配到了所有出现的“FOO”和“foo”。
1.2.3 多行模式(m)
多行模式改变了
代码示例:
const regexSingleLine = /^foo/; // 单行模式 const regexMultiLine = /^foo/m; // 多行模式 const str = 'foo foo'; const matchesSingleLine = str.match(regexSingleLine); const matchesMultiLine = str.match(regexMultiLine); console.log(matchesSingleLine); // 输出: [ 'foo', index: 0, input: 'foo foo', groups: undefined ] console.log(matchesMultiLine); // 在某些环境中可能不会按预期工作,因为match()方法不完全支持多行模式 // 使用exec()方法在多行字符串中查找所有匹配项 let regexMultiLineExec = /^foo/m; let result; while ((result = regexMultiLineExec.exec(str)) !== null) { console.log(result[0]); // 输出每行匹配的'foo' } // 输出: // foo // foo
注意:在使用
总结
模式 | 描述 | 示例 |
---|---|---|
全局(g) | 搜索整个字符串以找到所有匹配项 | |
不区分大小写(i) | 在匹配时忽略大小写 | |
多行(m) | 使 |
在实际应用中,这些模式可以单独使用,也可以组合使用,以满足特定的匹配需求。例如,
1.3 特殊字符和字符类
1.3.1 特殊字符和字符类
- d:匹配任何数字字符,等同于
[0-9] 。 - w:匹配任何字母、数字或下划线字符,等同于
[A-Za-z0-9_] 。 - .:匹配除换行符(
、
)之外的任何字符。
- *:匹配前面的子表达式零次或多次。
- +:匹配前面的子表达式一次或多次。
- ?:匹配前面的子表达式零次或一次。
- {n}:n 是一个非负整数,匹配前面的子表达式恰好 n 次。
- {n,}:n 是一个非负整数,匹配前面的子表达式至少 n 次。
- {n,m}:m 和 n 均为非负整数,且 n <= m,匹配前面的子表达式至少 n 次且最多 m 次。
代码示例
// d 示例:匹配数字 const regexDigits = /d+/; const strDigits = '123abc456'; const matchDigits = strDigits.match(regexDigits); console.log(matchDigits[0]); // 输出: "123" (只会匹配到第一个连续的数字序列) // w 示例:匹配字母、数字或下划线 const regexWordChars = /w+/; const strWordChars = 'hello_world123'; const matchWordChars = strWordChars.match(regexWordChars); console.log(matchWordChars[0]); // 输出: "hello_world123" // . 示例:匹配任意字符(换行符除外) const regexAnyChar = /a.b/; const strAnyChar = 'axb ayb'; const matchAnyChar = strAnyChar.match(regexAnyChar); console.log(matchAnyChar[0]); // 输出: "axb" (不会匹配换行后的"ayb") // * 示例:匹配前面的字符零次或多次 const regexStar = /ab*c/; const strStar = 'acabcabbc'; const matchStar = strStar.match(regexStar); console.log(matchStar[0]); // 输出: "abbc" (匹配尽可能多的"b") // + 示例:匹配前面的字符一次或多次 const regexPlus = /ab+c/; const strPlus = 'acabcabbc'; const matchPlus = strPlus.match(regexPlus); console.log(matchPlus[0]); // 输出: "abbc" (至少匹配一次"b") // ? 示例:匹配前面的字符零次或一次 const regexQuestion = /ab?c/; const strQuestion = 'acbabc'; const matchQuestion = strQuestion.match(regexQuestion); console.log(matchQuestion[0]); // 输出: "ac" (可以没有"b") // {n} 示例:匹配前面的字符恰好 n 次 const regexExact = /ab{2}c/; const strExact = 'abbcabcab'; const matchExact = strExact.match(regexExact); console.log(matchExact[0]); // 输出: "abbc" (恰好匹配两次"b") // {n,} 示例:匹配前面的字符至少 n 次 const regexAtLeast = /ab{2,}c/; const strAtLeast = 'abbcabbbbc'; const matchAtLeast = strAtLeast.match(regexAtLeast); console.log(matchAtLeast[0]); // 输出: "abbbbc" (至少匹配两次"b",尽可能多地匹配) // {n,m} 示例:匹配前面的字符至少 n 次,但不超过 m 次 const regexRange = /ab{2,4}c/; const strRange = 'abbcabbbbcabbbbbc'; const matchRange = strRange.match(regexRange); console.log(matchRange[0]); // 输出: "abbbbc" (匹配两到四次"b",尽可能多地匹配)
总结
特殊字符/字符类 | 描述 | 示例 |
---|---|---|
匹配任何数字字符 | ||
匹配任何字母、数字或下划线字符 | ||
匹配除换行符之外的任何字符 | ” |
|
匹配前面的子表达式零次或多次 | ||
匹配前面的子表达式一次或多次 | ||
匹配前面的子表达式零次或一次 | ||
匹配前面的子表达式恰好 n 次 | ||
匹配前面的子表达式至少 n 次 | ||
匹配前面的子表达式至少 n 次且最多 m 次 |
这个图表总结了特殊字符和字符类的用法,以及它们如何与数量词结合使用来定义更具体的匹配模式。在实际应用中,这些特殊字符和字符类可以单独使用,也可以组合使用,以满足特定的匹配需求。