正则

正则表达式 属于 JavaScript

9 个练习

关于 正则表达式

JavaScript 中的正则表达式

正则表达式(Regular Expression,或 Regex)是一串字符,我们可以用它来定位和操作字符串中的某些元素。因此,我们可以:

  • 搜索字符串中的文本
  • 替换字符串中的子串
  • 提取字符串中的信息

这个概念聚焦于在 JavaScript 中使用正则表达式。如果你想学习如何编写正则表达式,Eloquent JavaScript 也许是个不错的资源。

💡 JavaScript 的正则表达式风格是该语言 ECMA-262 标准的一部分。这意味着你不必担心浏览器特定的兼容性问题。

如何创建正则表达式

在 JavaScript 中,正则表达式大多写作 /pattern/modifiers 的形式,其中“pattern”是主体正则,“modifiers”是一系列字符,我们可以加上它们来指定特殊选项(就像超能力一样)。

不过,创建正则表达式有两种方式:

  1. 正则表达式字面量:
const regex = /[a-z]/;
  1. 构造函数RegExp:
const regex = new RegExp('[a-z]');

两种情况下,JavaScript 都会用正则创建一个对象。建议默认使用字面量来写不可变的模式。

当正则会变化,或者我们还不知道它是什么(比如来自输入)时,可以使用 RegExp 构造函数。

🏴‍☠️ 标志

正则表达式有一些可选的“超能力”,叫做flags,它们能带来额外的功能。这些标志可以单独使用,也可以以任意顺序组合使用,并且是正则表达式的一部分。

常用的标志有:

  • /g - 全局搜索
  • /i - 忽略大小写
  • /m - 多行搜索

来看一个简单的例子:

const re = /home/gi;
const str = 'Home, sweet home.';

str.match(re);

// => ["Home", "home"]

g字符让我们能解析出字符串中所有可能的匹配。没有这个功能,JavaScript 只会提取出第一个Home匹配。

忽略大小写标志/i让我们在查找模式时更加灵活。这样一来,我们要找的内容是大写UPPERCASE还是小写lowercase都无所谓。

使用RegExp构造函数时,添加标志的语法不一样。这种情况下,我们只需把标志作为第二个实参传入。

常用函数

当正则表达式与 JavaScript 内置函数结合时,我们就有了一些强大的方式来操作字符串、从字符串中获取数据。

test()方法非常适合用来搜索,并判断某个目标值是否存在于给定的字符串中。它会返回一个布尔值,true或false。

match()方法会从给定的字符串中提取正则表达式的匹配,返回一个包含匹配及相关信息的数组。

该用哪一个呢? 如果你想快速检查字符串中是否存在某个值,就用test();如果你需要使用那个值,或者想了解关于匹配的更多信息,就用match()。

Test

test()方法会在一段正则表达式和一个指定字符串之间执行匹配搜索,返回 true 或 false。

const str = 'It is difficult to test if you have a virus';
const result = /virus$/.test(str);

console.log(result);

// => true

Match

好吧,但如果我们想拿到正则表达式搜索的实际值,该怎么办呢?

match()方法不只是返回一个布尔值,而是返回一个有用的数组,数组的内容取决于是否找到匹配。

这样,我们既能搜索,也能提取任意字符串中的信息。例如:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';
const regex1 = /someone/;
const regex2 = /happy/;

funnyQuote.match(regex1);
// => ["someone", index: 3, input: "If you see someone crying, ask if it is because of their haircut.", groups: undefined]

funnyQuote.match(regex2);
// => null

当带有全局搜索标志/g时,该方法不会只返回那一个匹配以及下标、输入等有用信息,而是返回数组中出现的所有匹配:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';

const regex3 = /if/gi;

funnyQuote.match(regex3);
// => ["If", "if"];

Replace

JavaScript 中的replace()方法让我们可以在给定的字符串中搜索某个值,并用新的值替换它。

string.replace(searchValue, newValue);

用来搜索替换的模式可以是一个字符串,也可以是一个正则表达式。

let string = 'I like dogs!';
let result = string.replace('dogs', 'cats');

let string = 'I would love to travel to Japan';
let result = string.replace(/Japan/g, 'Hawaii');

此外,我们还可以在替换位置传入一个函数,对每个值做额外的改动。

let text = 'Say hello to the chatbot.';
let result = text.replace(/chatbot|hello/gi, function (word) {
  return word.toUpperCase();
});
// => "Say HELLO to the CHATBOT"

💡 总的来说,把正则表达式和replace()方法结合起来,是一种更动态的替换元素的方式。只用单个字符串可能会受到限制。

Split

JavaScript 中的split()方法展示了用正则表达式使用和操作字符串的另一种方式。

这里,我们用正则来识别某个模式,从而切分给定的字符串,例如str.split(/[,.\s]/)。这个模式会用作separator。

const str = 'hello,user.how are.you';

const result = str.split(/[,.\s]/);

console.log(result);
// => ['hello', 'user', 'how', 'are', 'you']

性能

就性能而言,两者都会创建一个 RegExp 对象。主要区别在于正则被编译的频率:

  • 使用Regular Expression Literal:在初始的代码解析和编译时编译一次
  • 使用RegExp()语法:每次创建新对象时都会编译

使用字面量语法可能是更好的选择,不仅因为性能,还因为简单、易读。更多细节可以看看这个 Stackoverflow 讨论。

  1. 它更简短,也不会逼着你用类似类的构造函数去思考。
  2. 使用RegExp()构造函数时,你还需要转义引号,并把反斜杠双重转义。这会让本就难读、难懂的正则表达式更加难上加难。
通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 正则表达式