Logo
Section 1 / 3

字符集

学习如何使用字符集创建精确的正则表达式。

导入

字符集

学习如何使用字符集创建精确的正则表达式。

字符集概述

正如其名,字符集是一组字符。

首先,回顾一下通配符章节中的示例:你曾创建了一个正则表达式来匹配 "Boat"、"Bent"、"Boot"、"Beat" 等文本,使用的正则表达式是 /B..t/。这个正则表达式不够精确,因为它也会匹配 "Best"、"Belt" 等文本。再来看另一组文本 "boat"、"Boat"。要匹配这些文本,可以使用不区分大小写的标志(i)。我们可以通过字符集来实现匹配。

字符集的工作原理

字符集特性:从给定的字符集合中,正则表达式引擎将选择与文本匹配的任意一个字符(每次只匹配一个字符)。方括号内的字符被视为字符集的元素。例如,[abc] 就是一个字符集。当正则表达式引擎开始在文本中搜索模式时,它会将文本中的字符与字符集中列出的所有字符进行匹配。

让我们通过一个例子来理解这一点。假设你的文本是 "This is a book",正则表达式为 /[abc]/g。首先,引擎从文本中取出字符 "T",然后将其与字符集中的 "a"、"b" 或 "c" 进行比较。由于 "T" 不匹配任何字符,引擎会移动到下一个字符,依此类推。当遇到文本中的字符 "a" 时,就会匹配成功;同样地,"book" 中的字符 "b" 也会匹配。正则表达式引擎最终返回结果为 "a,b"。文本中没有其他字符能匹配该模式。

再看另一个例子:假设你想匹配 "head"、"heat"、"hear"。一个可能的正则表达式是 /hea./。这个表达式会匹配大量文本,如 "heal"、"heaT"、"heaR" 等。但你只想匹配上述三个特定文本。解决这个问题的方法是使用字符集。将所需的字符放入字符集中 [drt]。现在,正则表达式会先进行字面匹配 "hea",然后匹配字符集中的任意一个字符。因此,正则表达式应为 /hea[drt]/g,仅匹配所需文本,不会匹配所有可能的组合。始终记住,应编写精准的正则表达式,只匹配所需内容。通配符会因回溯而增加计算开销。

1var str = "heat, hear, head, heal"; 2console.log(str.match(/hea[drt]/g)); 3 4// console.log(str.match(/hea./g)); 5// 不建议对简单搜索使用通配符,正则表达式应尽可能具体。

在同一个正则表达式中,字符集可以多次使用。再举一个例子:假设你要匹配 "apple"、"Apple"、"applE"、"ApplE"。观察这些文本,你会发现只有首尾字符不同,中间部分相同。将起始和结尾字符放入字符集中。第一个字符集为 [aA],最后一个字符集为 [eE],中间部分为 ppl。将三部分组合起来,正则表达式变为 /[aA]ppl[eE]/g。该表达式将生成以下组合:"apple"、"applE"、"Apple"、"ApplE"。

在字符集中,也可以使用数字和特殊字符,用法与字母相同。

使用字符集匹配文本的挑战

编写正则表达式,匹配所有大于等于 "9810" 且小于等于 "9829" 的数字。解决方案中需使用两个字符集。

思考时间
思考时间
1var match = function(str){ 2 // 例如:return str.match(/[23]12[46]/g) 3 return str.match(); 4}

上述挑战的解决方案

首先,需要匹配的数字范围是 "9810 <= number <= 9829"。所有数字都以 "98" 开头,这部分可直接作为字面量匹配。第三位数字是 "1" 或 "2",因此字符集为 [12]。第四位数字是 "0 到 9" 之间的任意数字,字符集可写为 [0123456789],或其任意排列形式,如 [0987654321] 或 [1234567890],这些都能正常工作。因此,正则表达式为 /98[12][0123456789]/。

通配符与字符集结合使用

通配符也可以出现在字符集中。大多数情况下它们保持字面含义,但有少数例外,需要转义:

  • ]:右方括号必须转义,否则正则引擎会认为字符集已结束。
  • -:连字符必须转义,因为它表示范围。
  • \:反斜杠必须转义,因为它用于转义其他字符。
  • ^:脱字符必须转义,因为它用于创建否定字符集。
1var str = "\\bc -bc ^bc ]bc" 2console.log(str.match(/[\]\\\-\^]bc/g)); 3 4// 调整元字符顺序,观察输出变化。 5// \\bc 表示 \bc,因为反斜杠本身也需要转义。

结合特殊字符与字符集的示例

假设你有一段包含成千上万条记录的文本,需要找出以下八种组合的所有出现情况:"(12)-4"、"(12)-5"、"(12]-4"、"(12]-5"、"(13)-4"、"(13)-5"、"(13]-4"、"(13]-5"。你的正则表达式应匹配:一个左括号,后跟两个数字,接着是一个圆括号或右方括号,再跟一个连字符,最后是一个数字。

你可能会想到使用通配符和字面匹配。但通配符会匹配大量文本,这不是理想方案。我们通过分步分析来构建正则表达式。

观察目标文本,它们都以左括号 "(" 开头。这说明必须将 "(" 视为字面字符。但括号是特殊字符,必须用反斜杠转义。接下来,所有文本的第二个字符都是 "1",可直接使用字面匹配。此时正则表达式为 /\(1/。第三个字符是 "2" 或 "3",可用包含这两个字符的字符集 [23]。正则表达式变为 /\(1[23]/。第四个字符较复杂,是 ")" 或 "]",也放入字符集中。

注意:字符集中大多数字符按字面处理,但右方括号 "]" 是例外,必须转义。因此,正则表达式变为 /\(1[23][\])]/。之后是字面连字符 "-",它在字符集中也有特殊含义(表示范围),因此也需要转义。最后一位是 "4" 或 "5",用 [45] 表示。最终正则表达式为 /\(1[23][\])]-[45]/。

学习字符集是不是很有趣?现在你应该已经掌握了字符集的工作原理,如何多次使用它,以及如何与特殊字符和数字结合使用。

字符

否定字符集