赞
踩
正则表达式 Regular expressions,缩写为 regex,或有时为 regexp,是你可能知道的真正强大和有用的概念之一。但它们可能令人生畏,特别是对初学的程序员来说,更是如此。
其实不一定是这样的。JavaScript 包括几个有用的方法,使正则表达式的使用更容易。在这些方法中,.match()
、.matchAll()
和 .replace()
方法可能是你最经常使用的。
在本教程中,我们将介绍这些方法,并看看为什么你会使用这些方法而不是其他的 JS 方法。
根据 MDN,正则表达式是“用于匹配字符串中字符组合的模式”。
这些模式有时可以包括特殊字符(*
,+
),断言(\W
,^
),组和范围((abc)
,[123]
),以及其他使正则如此强大但难以掌握的东西。
就其核心而言,正则就是在字符串中寻找模式——从测试一个字符串的单个字符到验证一个电话号码是否有效,都可以用正则表达式完成。
如果你对正则表达式是个新手,想在继续阅读之前做一些练习,可以看看我们的交互式编码挑战。
.match()
方法因此,如果正则是关于在字符串中寻找模式,你可能会问自己是什么使 .match()
方法如此有用?
不像 .test()
方法只是返回 true
或者 false
,.match()
将实际返回与你测试的字符串的匹配,例如:
- const csLewisQuote = 'We are what we believe we are.';
- const regex1 = /are/;
- const regex2 = /eat/;
-
- csLewisQuote.match(regex1); // ["are", index: 3, input: "We are what we believe we are.", groups: undefined]
-
- csLewisQuote.match(regex2); // null
这对一些项目来说真的很有帮助,特别是当你想在不改变原始字符串的情况下提取和操作你所匹配的数据时。
如果你只想知道一个搜索模式是否被找到,请使用 .test()
方法——它要快得多。
从 .match()
方法中你可以期待两个主要的返回值:
.match()
方法将返回一个包含匹配内容的数组。我们稍后会详细讨论这个问题。.match()
方法将返回 null
。你可能已经注意到了这一点,但如果你看上面的例子,.match()
只匹配 “are” 这个词的第一个实例。
很多时候,你会想知道一个模式与你所测试的字符串的匹配频率,所以让我们看看如何用 .match()
来实现。
如果有一个匹配,.match()
返回的数组有两种不同的模式,因为缺乏更好的术语。
第一种模式是不使用全局标志(g
)时,例如在上面的例子中:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /are/;
-
- csLewisQuote.match(regex); // ["are", index: 3, input: "We are what we believe we are.", groups: undefined]
在这种情况下,我们 .match()
一个数组,和包含第一个匹配项以及原始字符串中匹配项的索引、原始字符串本身,以及任何使用过的匹配组。
但是,假设你想看看 “are” 这个词在一个字符串中出现了多少次。要做到这一点,只需在你的正则表达式中添加全局搜索标志:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /are/g;
-
- csLewisQuote.match(regex); // ["are", "are"]
你不会得到非全局模式所包含的其他信息,但你会得到一个包含你正在测试的字符串中所有匹配的数组。
要记住的一件重要事情是,regex 是区分大小写的。例如,假设你想看看 “we” 这个词在你的字符串中出现了多少次:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /we/g;
-
- csLewisQuote.match(regex); // ["we", "we"]
在这种情况下,你要匹配的是一个小写的 “w” 和一个小写的 “e”,而后者只出现两次。
如果你想要 “we” 这个词的所有实例,无论它是大写还是小写,你有几个选择。
首先,你可以在用 .match()
方法测试之前对字符串使用 .toLowercase()
方法:
- const csLewisQuote = 'We are what we believe we are.'.toLowerCase();
- const regex = /we/g;
-
- csLewisQuote.match(regex); // ["we", "we", "we"]
或者如果你想保留原来的大小写,你可以在你的正则表达式中添加不区分大小写的搜索标志(i
):
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /we/gi;
-
- csLewisQuote.match(regex); // ["We", "we", "we"]
.matchAll()
方法现在你已经知道了关于 .match()
方法的所有情况,值得指出的是,最近引入了 .matchAll()
方法。
与 .match()
方法不同的是,.matchAll()
需要全局搜索标志(g
),并返回一个迭代器或一个空数组:
- const csLewisQuote = 'We are what we believe we are.';
- const regex1 = /we/gi;
- const regex2 = /eat/gi;
-
- [...csLewisQuote.matchAll(regex1)];
- // [
- // ["We", index: 0, input: "We are what we believe we are.", groups: undefined],
- // ["we", index: 12, input: "We are what we believe we are.", groups: undefined]
- // ["we", index: 23, input: "We are what we believe we are.", groups: undefined]
- // ]
-
- [...csLewisQuote.matchAll(regex2)]; // []
虽然它看起来只是一个更复杂的 .match()
方法,但 .matchAll()
的主要优势在于它能更好地处理捕获组。
下面是一个简单的例子:
- const csLewisRepeat = "We We are are";
- const repeatRegex = /(\w+)\s\1/g;
-
- csLewisRepeat.match(repeatRegex); // ["We We", "are are"]
.match()
- const csLewisRepeat = "We We are are";
- const repeatRegex = /(\w+)\s\1/g;
-
- [...repeatStr.matchAll(repeatRegex)];
-
- // [
- // ["We We", "We", index: 0, input: "We We are are", groups: undefined],
- // ["are are", "are", index: 6, input: "We We are are", groups: undefined],
- // ]
.matchAll()
虽然这只是勉强触及表面,但请记住,如果你使用 g
标志并希望得到 .match()
为单个匹配提供的所有额外信息(索引、原始字符串等),使用 .matchAll()
可能更好。
现在你知道了如何在字符串中匹配模式,你可能想对这些匹配做一些有用的事情。
一旦你找到一个匹配的模式,你最常做的事情之一就是用其他东西替换该模式。例如,你可能想把 “paidCodeCamp” 中的 “paid” 替换成 “free”。Regex 将是一个很好的方法来实现这一点。
由于 .match()
和 .matchAll()
返回每个匹配模式的索引信息,取决于你如何使用它,你可以用它来做一些花哨的字符串操作。但是有一个更简单的方法——通过使用 .replace()
方法。
使用 .replace()
,你所需要做的就是把你想匹配的字符串或正则表达式作为第一个参数传给它,把要替换的字符串作为第二个参数:
- const campString = 'paidCodeCamp';
- const fCCString1 = campString.replace('paid', 'free');
- const fCCString2 = campString.replace(/paid/, 'free');
-
- console.log(campString); // "paidCodeCamp"
- console.log(fCCString1); // "freeCodeCamp"
- console.log(fCCString2); // "freeCodeCamp"
最重要的是,.replace()
返回一个新的字符串,而原来的则保持不变。
与 .match()
方法类似,.replace()
只会替换它找到的第一个匹配模式,除非你使用带有 g
标志的 regex:
- const campString = 'paidCodeCamp is awesome. You should check out paidCodeCamp.';
- const fCCString1 = campString.replace('paid', 'free');
- const fCCString2 = campString.replace(/paid/g, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out paidCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
与之前类似,无论你传递的是字符串还是正则表达式作为第一个参数,都要记住匹配模式是区分大小写的:
- const campString = 'PaidCodeCamp is awesome. You should check out PaidCodeCamp.';
- const fCCString1 = campString.replace('Paid', 'free');
- const fCCString2 = campString.replace(/paid/gi, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out PaidCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
就像 .match()
有一个更新的 .matchAll()
方法一样,.replace()
也有一个更新的 .replaceAll()
方法。
.replace()
和 .replaceAll()
之间唯一真正的区别是,如果你用 .replaceAll()
使用正则表达式,你需要使用全局搜索标志:
- const campString = 'paidCodeCamp is awesome. You should check out paidCodeCamp.';
- const fCCString1 = campString.replaceAll('paid', 'free');
- const fCCString2 = campString.replaceAll(/paid/g, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
.replaceAll()
的真正好处是它的可读性更强一些,当你把一个字符串作为第一个参数传给它时,它将替换所有匹配的模式。
现在你知道了用 regex 和一些内置的 JS 方法匹配和替换部分字符串的基本知识。这些都是非常简单的例子,但我希望它仍然显示了即使是一点点的 regex 也可以是多么强大。
这对你有帮助吗?你是如何使用 .match()
、.matchAll()
、.replace()
和 .replaceAll()
方法的?
Regular expressions, abbreviated as regex, or sometimes regexp, are one of those concepts that you probably know is really powerful and useful. But they can be daunting, especially for beginning programmers.
It doesn't have to be this way. JavaScript includes several helpful methods that make using regular expressions much more manageable. Of the included methods, the .match()
, .matchAll()
, and .replace()
methods are probably the ones you'll use most often.
In this tutorial, we'll go over the ins and outs of those methods, and look at some reasons why you might use them over the other included JS methods
According to MDN, regular expressions are "patterns used to match character combinations in strings".
These patterns can sometimes include special characters (*
, +
), assertions (\W
, ^
), groups and ranges ((abc)
, [123]
), and other things that make regex so powerful but hard to grasp.
At its core, regex is all about finding patterns in strings – everything from testing a string for a single character to verifying that a telephone number is valid can be done with regular expressions.
If you're brand new to regex and would like some practice before reading on, check out our interactive coding challenges.
.match()
methodSo if regex is all about finding patterns in strings, you might be asking yourself what makes the .match()
method so useful?
Unlike the .test()
method which just returns true
or false
, .match()
will actually return the match against the string you're testing. For example:
- const csLewisQuote = 'We are what we believe we are.';
- const regex1 = /are/;
- const regex2 = /eat/;
-
- csLewisQuote.match(regex1); // ["are", index: 3, input: "We are what we believe we are.", groups: undefined]
-
- csLewisQuote.match(regex2); // null
This can be really helpful for some projects, especially if you want to extract and manipulate the data that you're matching without changing the original string.
If all you want to know is if a search pattern is found or not, use the .test()
method – it's much faster.
There are two main return values you can expect from the .match()
method:
.match()
method will return an array with the match. We'll go into more detail about this in a bit..match()
method will return null
.Some of you might have already noticed this, but if you look at the example above, .match()
is only matching the first occurrence of the word "are".
A lot of times you'll want to know how often a pattern is matched against the string you're testing, so let's take a look at how to do that with .match()
.
If there's a match, the array that .match()
returns had two different modes, for lack of a better term.
The first mode is when the global flag (g
) isn't used, like in the example above:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /are/;
-
- csLewisQuote.match(regex); // ["are", index: 3, input: "We are what we believe we are.", groups: undefined]
In this case, we .match()
an array with the first match along with the index of the match in the original string, the original string itself, and any matching groups that were used.
But say you want to see how many times the word "are" occurs in a string. To do that, just add the global search flag to your regular expression:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /are/g;
-
- csLewisQuote.match(regex); // ["are", "are"]
You won't get the other information included with the non-global mode, but you'll get an array with all the matches in the string you're testing.
An important thing to remember is that regex is case sensitive. For example, say you wanted to see how many times the word "we" occurs in your string:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /we/g;
-
- csLewisQuote.match(regex); // ["we", "we"]
In this case, you're matching a lowercase "w" followed by a lowercase "e", which only occurs twice.
If you'd like all instances of the word "we" whether it's upper or lowercase, you have a couple of options.
First, you could use the .toLowercase()
method on the string before testing it with the .match()
method:
- const csLewisQuote = 'We are what we believe we are.'.toLowerCase();
- const regex = /we/g;
-
- csLewisQuote.match(regex); // ["we", "we", "we"]
Or if you want to preserve the original case, you could add the case-insensitive search flag (i
) to your regular expression:
- const csLewisQuote = 'We are what we believe we are.';
- const regex = /we/gi;
-
- csLewisQuote.match(regex); // ["We", "we", "we"]
.matchAll()
methodNow that you know all about the .match()
method, it's worth pointing out that the .matchAll()
method was recently introduced.
Unlike the .match()
method which returns an array or null
, .matchAll()
requires the global search flag (g
), and returns either an iterator or an empty array:
- const csLewisQuote = 'We are what we believe we are.';
- const regex1 = /we/gi;
- const regex2 = /eat/gi;
-
- [...csLewisQuote.matchAll(regex1)];
- // [
- // ["We", index: 0, input: "We are what we believe we are.", groups: undefined],
- // ["we", index: 12, input: "We are what we believe we are.", groups: undefined]
- // ["we", index: 23, input: "We are what we believe we are.", groups: undefined]
- // ]
-
- [...csLewisQuote.matchAll(regex2)]; // []
While it seems like just a more complicated .match()
method, the main advantage that .matchAll()
offers is that it works better with capture groups.
Here's a simple example:
- const csLewisRepeat = "We We are are";
- const repeatRegex = /(\w+)\s\1/g;
-
- csLewisRepeat.match(repeatRegex); // ["We We", "are are"]
.match()
- const csLewisRepeat = "We We are are";
- const repeatRegex = /(\w+)\s\1/g;
-
- [...repeatStr.matchAll(repeatRegex)];
-
- // [
- // ["We We", "We", index: 0, input: "We We are are", groups: undefined],
- // ["are are", "are", index: 6, input: "We We are are", groups: undefined],
- // ]
.matchAll()
While that just barely scratches the surface, keep in mind that it's probably better to use .matchAll()
if you're using the g
flag and want all the extra information that .match()
provides for a single match (index, the original string, and so on).
.replace()
methodSo now that you know how to match patterns in strings, you'll probably want to do something useful with those matches.
One of the most common things you'll do once you find a matching pattern is replace that pattern with something else. For example, you might want to replace "paid" in "paidCodeCamp" with "free". Regex would be a good way to do that.
Since .match()
and .matchAll()
return information about the index for each matching pattern, depending on how you use it, you could use that to do some fancy string manipulation. But there's an easier way – by using the .replace()
method.
With .replace()
, all you need to do is pass it a string or regular expression you want to match as the first argument, and a string to replace that matched pattern with as the second argument:
- const campString = 'paidCodeCamp';
- const fCCString1 = campString.replace('paid', 'free');
- const fCCString2 = campString.replace(/paid/, 'free');
-
- console.log(campString); // "paidCodeCamp"
- console.log(fCCString1); // "freeCodeCamp"
- console.log(fCCString2); // "freeCodeCamp"
The best part is that .replace()
returns a new string, and the original remains the same.
Similar to the .match()
method, .replace()
will only replace the first matched pattern it finds unless you use regex with the g
flag:
- const campString = 'paidCodeCamp is awesome. You should check out paidCodeCamp.';
- const fCCString1 = campString.replace('paid', 'free');
- const fCCString2 = campString.replace(/paid/g, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out paidCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
And similar to before, whether you pass a string or a regular expression as the first argument, it's important to remember that the matching pattern is case sensitive:
- const campString = 'PaidCodeCamp is awesome. You should check out PaidCodeCamp.';
- const fCCString1 = campString.replace('Paid', 'free');
- const fCCString2 = campString.replace(/paid/gi, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out PaidCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
.replaceAll()
methodJust like how .match()
has a newer .matchAll()
method, .replace()
has a newer .replaceAll()
method.
The only real difference between .replace()
and .replaceAll()
is that you need to use the global search flag if you use a regular expression with .replaceAll()
:
- const campString = 'paidCodeCamp is awesome. You should check out paidCodeCamp.';
- const fCCString1 = campString.replaceAll('paid', 'free');
- const fCCString2 = campString.replaceAll(/paid/g, 'free');
-
- console.log(fCCString1); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
- console.log(fCCString2); // "freeCodeCamp is awesome. You should check out freeCodeCamp."
The real benefit with .replaceAll()
is that it's a bit more readable, and replaces all matched patterns when you pass it a string as the first argument.
That's it! Now you know the basics of matching and replacing parts of strings with regex and some built-in JS methods. These were pretty simple examples, but I hope it still showed how powerful even a little bit of regex can be.
Was this helpful? How do you use the .match()
, .matchAll()
, .replace()
, and .replaceAll()
methods?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。