11日 四月 2020

字符类

考虑一个实际的任务 – 我们有一个电话号码,例如 "+7(903)-123-45-67",我们需要将其转换为纯数字:79035419441

为此,我们可以查找并删除所有非数字的内容。字符类可以帮助解决这个问题。

字符类(Character classes) 是一个特殊的符号,匹配特定集中的任何符号。

首先,让我们探索“数字”类。它写为 \d,对应于“任何一个数字”。

例如,让我们找到电话号码的第一个数字:

let str = "+7(903)-123-45-67";

let regexp = /\d/;

alert( str.match(regexp) ); // 7

如果没有标志 g,则正则表达式仅查找第一个匹配项,即第一个数字 \d

让我们添加 g标志来查找所有数字:

let str = "+7(903)-123-45-67";

let regexp = /\d/g;

alert( str.match(regexp) ); // array of matches: 7,9,0,3,1,2,3,4,5,6,7

// let's make the digits-only phone number of them:
alert( str.match(regexp).join('') ); // 79035419441

这是数字的字符类。还有其他字符类。

最常用的是:

\d(“d” 来自 “digit”)
数字:从 09 的字符。
\s(“s” 来自 “space”)
空格符号:包括空格,制表符 \t,换行符 \n 和其他少数稀有字符,例如 \v\f\r
\w(“w” 来自 “word”)
“单字”字符:拉丁字母或数字或下划线 _。非拉丁字母(如西里尔字母或印地文)不属于 \w

例如,\d\s\w表示“数字”,后跟“空格字符”,后跟“单字字符”,例如 1 a

正则表达式可能同时包含常规符号和字符类。

例如,CSS\d 匹配字符串 CSS 与后面的数字:

let str = "Is there CSS4?";
let regexp = /CSS\d/

alert( str.match(regexp) ); // CSS4

我们还可以使用许多字符类:

alert( "I love HTML5!".match(/\s\w\w\w\w\d/) ); // ' HTML5'

匹配项(每个正则表达式字符类都有对应的结果字符):

反向类

对于每个字符类,都有一个“反向类”,用相同的字母表示,但要以大写书写形式。

“反向”表示它与所有其他字符匹配,例如:

\D
非数字:除 \d 以外的任何字符,例如字母。
\S
非空格符号:除 \s 以外的任何字符,例如字母。
\W
非单字字符:除 \w 以外的任何字符,例如非拉丁字母或空格。

在这一章的开头,我们看到了如何从 +7(903)-123-45-67 这样的字符串中创建一个只包含数字的电话号码: 找到所有的数字并将它们连接起来。

let str = "+7(903)-123-45-67";

alert( str.match(/\d/g).join('') ); // 79031234567

另一种快捷的替代方法是查找非数字 \D 并将其从字符串中删除:

let str = "+7(903)-123-45-67";

alert( str.replace(/\D/g, "") ); // 79031234567

点(.)是匹配“任何字符”

. 是一种特殊字符类,它与 “除换行符之外的任何字符” 匹配。

例如:

alert( "Z".match(/./) ); // Z

或在正则表达式中间:

let regexp = /CS.4/;

alert( "CSS4".match(regexp) ); // CSS4
alert( "CS-4".match(regexp) ); // CS-4
alert( "CS 4".match(regexp) ); // CS 4 (space is also a character)

请注意,点表示“任何字符”,而不是“缺少字符”。必须有一个与之匹配的字符:

alert( "CS4".match(/CS.4/) ); // null, no match because there's no character for the dot

带有“s”标志时点字符类严格匹配任何字符

默认情况下,点与换行符 \n 不匹配。

例如,正则表达式 A.B 匹配 A,然后匹配 B 和它们之间的任何字符,除了换行符\n

alert( "A\nB".match(/A.B/) ); // null (no match)

在许多情况下,当我们希望用点来表示“任何字符”(包括换行符)时。

这就是标志 s 所做的。如果有一个正则表达式,则点 . 实际上匹配任何字符:

alert( "A\nB".match(/A.B/s) ); // A\nB (match!)
不支持 Firefox、IE、Edge

使用前可从 https://caniuse.com/#search=dotall 确认以获得最新的支持状态。在撰写本文时,它不包括 Firefox、IE、Edge。

幸运的是,有一种替代方法可以在任何地方使用。我们可以使用诸如 [\s\S] 之类的正则表达式来匹配“任何字符”。

alert( "A\nB".match(/A[\s\S]B/) ); // A\nB (match!)

模式 [\s\S] 从字面上说:“空格字符或非空格字符”。换句话说,“任何东西”。我们可以使用另一对互补的类,例如 [\d\D]。甚至是 [^] —— 意思是匹配任何字符,除了什么都没有。

如果我们希望两种“点”都使用相同的模式,也可以使用此技巧:实际的点 . 具有常规方式(“不包括换行符”)以及一种使用 [\s\S] 或类似形式匹配“任何字符”。

注意空格

通常我们很少注意空格。对我们来说,字符串 1-51 - 5 几乎相同。

但是,如果正则表达式未考虑空格,则可能无法正常工作。

让我们尝试查找由连字符(-)分隔的数字:

alert( "1 - 5".match(/\d-\d/) ); // null, no match!

让我们修复一下,在正则表达式中添加空格:\ d-\ d`:

alert( "1 - 5".match(/\d - \d/) ); // 1 - 5, now it works
// or we can use \s class:
alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, also works

空格是一个字符。与其他字符同等重要。

我们无法在正则表达式中添加或删除空格,并且期望能正常工作。

换句话说,在正则表达式中,所有字符都很重要,空格也很重要。

总结

存在以下字符类:

  • \d —— 数字。
  • \D —— 非数字。
  • \s —— 空格符号,制表符,换行符。
  • \S —— 除了 \s
  • \w —— 拉丁字母,数字,下划线 '_'
  • \W —— 除了 \w
  • . —— 任何带有 's' 标志的字符,否则为除换行符 \n之外的任何字符。

……但这还不是全部!

JavaScript 用于字符串的 Unicode 编码提供了许多字符属性,例如:这个字母属于哪一种语言(如果它是一个字母)?它是标点符号吗?等等。

我们也可以通过这些属性进行搜索。这需要标志 u,在下一篇文章中介绍。

教程路线图

评论

在评论之前先阅读本内容…
  • 如果你发现教程有错误,或者有其他需要修改和提升的地方 — 请 提交一个 GitHub issue 或 pull request,而不是在这评论。
  • 如果你对教程的内容有不理解的地方 — 请详细说明。
  • 使用 <code> 标签插入只有几个词的代码,插入多行代码可以使用 <pre> 标签,对于超过 10 行的代码,建议你使用沙箱(plnkrJSBincodepen…)