如何在 JavaScript 中创建正则表达式
在 JavaScript 中创建正则表达式有两种方法。第一个是使用正则表达式文字语法,第二个是使用 RegExp()
构造函数。
要使用正则表达式文字语法创建正则表达式,您必须将模式括在两个正斜杠 ( /
) 内,如下所示:
js
/regex pattern/
如果你想使用一个或多个标志,它必须在第二个斜杠之后:
js
/regex pattern/flag
根据您的用例,您可能必须将正则表达式分配给变量:
js
const regex = /regex pattern/flag
该标志可以是 JavaScript 正则表达式引擎中可用的任何标志。
如果要使用 RegExp()
构造函数创建正则表达式,则必须使用 new
关键字,然后将模式和标志放在 RegExp()
括号内。
语法如下:
js
const regex = new RegExp("regex pattern", "flag");
由于 RegExp()
是一个构造函数,因此其中有一些方法和属性可供您使用正则表达式。无论您使用文字语法 //
还是 RegExp()
构造函数创建模式,方法和属性都可用。
RegExp()
构造函数的方法
RegExp()
构造函数的方法在 RegExp.prototype
上定义。您可以通过在浏览器控制台中键入 RegExp().__proto__
并点击 ENTER
来快速检查方法(和属性)。这些方法包括 test()
、 exec()
和 toString()
。
除了这三个之外,有些方法还采用正则表达式作为参数。但最好在"使用正则表达式的字符串方法"下讨论它们,因为它们的核心是采用正则表达式作为参数的字符串方法。
Let's take a look at what test()
, exec()
, and toString()
do.
让我们看看 test()
、 exec()
和 toString()
做了什么。
The test()
Method test()
方法
test()
方法测试正则表达式和测试字符串之间的匹配,并返回一个布尔值作为结果。如果匹配,则返回 true
,如果不匹配,则返回 false
。
在下面的示例中,有一个模式 /freeCodeCamp/
的匹配:
js
const re = /freeCodeCamp/;
const testStr =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
console.log(re.test(testStr)); //true
但在下面的示例中,模式 /fcc/
不匹配,因此 test()
方法返回 false
:
js
const re = /fcc/;
const testStr =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
console.log(re.test(testStr)); //false
除了针对字符串测试随机模式之外, test()
方法在表单验证中也很有用。
The exec()
Method exec()
方法
exec()
方法在测试字符串中执行匹配搜索,并返回一个包含有关第一个匹配的详细信息的数组。如果没有匹配,则返回 null
。
这是一个例子:
js
const re = /freeCodeCamp/;
const testStr =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
console.log(re.exec(testStr));
这是结果的屏幕截图:
如果您想让 exec()
方法返回所有匹配项,您可以在模式上使用 g
标志,然后使用 while
循环进行循环:
js
const re = /freeCodeCamp/g;
const testStr =
"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
let match;
while ((match = re.exec(testStr)) !== null) {
console.log(match[0]);
}
结果在控制台中如下所示:
您可以通过以下方式访问匹配项的索引来进一步进行操作:
js
const re = /freeCodeCamp/g;
const testStr =
"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
let match;
while ((match = re.exec(testStr)) !== null) {
console.log(match[0]);
// Access the indices of the matches
console.log(match.index);
}
如果没有匹配, exec()
返回 null:
js
const re = /fcc/;
const testStr =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp.";
console.log(re.exec(testStr)); //null
The toString()
Method toString()
方法
toString()
方法将正则表达式模式转换为字符串。在 JavaScript 中, toString()
方法存在于每个对象中。正则表达式被视为幕后的对象,这就是为什么您可以使用 new
关键字创建它们。
在正则表达式模式上使用此方法会将模式转换为字符串:
js
const pattern = /freeCodeCamp/;
const strPattern = pattern.toString();
console.log(strPattern, typeof strPattern); // /freeCodeCamp/ string
即使您使用 RegExp()
构造函数创建模式,您也会以相同的方式获得结果:
js
const pattern = new RegExp('freeCodeCamp');
const strPattern = pattern.toString();
console.log(strPattern, typeof strPattern); // /freeCodeCamp/ string
如果模式中有一个标志,它将作为字符串的一部分返回:
js
const pattern = /freeCodeCamp/gi;
const strPattern = pattern.toString();
console.log(strPattern, typeof strPattern); // /freeCodeCamp/gi string
RegExp()
构造函数的属性
RegExp()
构造函数的属性在 RegExp.prototype
上定义。他们包括:
RegExp.prototype.global
RegExp.prototype.source
RegExp.prototype.flags
RegExp.prototype.multiline
RegExp.prototype.ignoreCase
RegExp.prototype.dotAll
RegExp.prototype.sticky
RegExp.prototype.unicode
简而言之,有 global
、 source
、 flags
、 multiline
、 ignoreCase
、 dotAll
和 unicode
。 大多数属性检查是否使用某个标志。让我们看一下每个属性的工作原理。
global
属性
全局属性检查 g
标志是否与正则表达式模式一起使用。如果模式具有 g
标志,则返回 true
,否则返回 false
。
请记住 global
( g
) 标志指示正则表达式模式不应仅返回第一个匹配项,而应返回所有匹配项。 以下是 global
属性在代码中的工作原理:
js
const re1 = /freeCodeCamp/g;
const re2 = /freeCodeCamp/;
const re3 = new RegExp('freeCodeCamp');
const re4 = new RegExp('freeCodeCamp', 'g');
console.log(re1.global); //true
console.log(re2.global); //false
console.log(re3.global); //false
console.log(re4.global); //true
flag
属性
flag 属性按字母顺序返回您在正则表达式模式中使用的标志。也就是说, g
在 i
之前, i
在 m
之前, m
在 y
之前, 等等。
在下面的代码中,您可以看到 g
标志位于 i
之前,而 m
位于 y
之前:
js
const re1 = /freeCodeCamp/gi;
const re2 = new RegExp('freeCodeCamp', 'my');
console.log(re1.flags); //gi
console.log(re2.flags); //my
source
属性
source
属性以字符串形式返回正则表达式模式。因此,它的行为类似于 toString()
方法。 source
属性和 toString()
方法之间的区别在于 source
属性排除了与模式一起使用的标志。此外, source
属性不显示用于创建正则表达式的文字正斜杠。
在下面的代码中,您可以看到正斜杠没有被打印,标志也被省略,并且 type
是一个字符串:
js
const re1 = /freeCodeCamp/gi;
const re2 = new RegExp('freeCodeCamp', 'my');
const re1Source = re1.source;
const re2Source = re2.source;
console.log(re1Source, typeof re1Source); // freeCodeCamp string
console.log(re2Source, typeof re2Source); // freeCodeCamp string
multiline
属性
multiline
标志是 RegExp()
构造函数的另一个布尔属性。它通过返回 true
或 false
来指定 multiline
标志是否与模式一起使用。
请记住 multiline
( m
) 标志指示测试字符串应被视为具有多行的文本。 以下是 multiline
属性的实际工作原理:
js
const re1 = /freeCodeCamp/gi;
const re2 = new RegExp('freeCodeCamp', 'my');
const re1Source = re1.multiline;
const re2Source = re2.multiline;
console.log(re1Source); //false
console.log(re2Source); // true
ignoreCase 属性
ignoreCase
属性指定是否在正则表达式模式中使用不区分大小写的标志 ( i
)。如果您使用 i
标志,它会返回 true
;如果您不使用它,它会返回 false
。
js
const re1 = /freeCodeCamp/i;
const re2 = /freeCodeCamp/;
const re3 = new RegExp('freeCodeCamp', 'i');
const re4 = new RegExp('freeCodeCamp');
console.log(re1.ignoreCase); //true
console.log(re2.ignoreCase); // false
console.log(re3.ignoreCase); // true
console.log(re4.ignoreCase); // false
Unicode
属性
unicode
属性可帮助您检查正则表达式模式中是否使用 Unicode ( u
) 标志。如果找到 u
标志,则返回 true
,否则返回 false
。
js
const re1 = /\u{1F1F3}\u{1F1EC}/u; //matches the Nigerian flag emoji
const re2 = /\u{1F1F3}\u{1F1EC}/;
const re3 = new RegExp('\u{1F1F3}\u{1F1EC}', 'u');
const re4 = new RegExp('\u{1F1F3}\u{1F1EC}');
console.log(re1.unicode); //true
console.log(re2.unicode); // false
console.log(re3.unicode); // true
console.log(re4.unicode); // false
sticky
属性
Sticky 属性指示是否在正则表达式中设置了粘性 ( y
) 标志。尽管这就是它的作用,但由于 lastIndex
属性,理解它仍然有点棘手。
设置 y
标志时,正在使用的正则表达式引擎将尝试匹配从 lastIndex
属性指定的确切位置开始的模式(不使用 g
标志)。如果找到匹配项, lastIndex
属性将立即更新为匹配结束后的位置。
为了帮助您更好地理解这一点,这里有一个带有注释的代码片段:
js
const re = /xyz/y;
const str = 'xyzxyz';
re.lastIndex = 0;
console.log(re.test(str)); // true -- there's a match at index 0 to 2
console.log(re.lastIndex); // 3
re.lastIndex = 1;
console.log(re.test(str)); // false -- no match at the specified index
console.log(re.lastIndex); // 0 -- resets to 0 because there's no match at the specified index
re.lastIndex = 3;
console.log(re.test(str)); // true -- there's a match at index 3 to 5
console.log(re.lastIndex); // 6
re.lastIndex = 6;
console.log(re.test(str)); // false
console.log(re.lastIndex); // 0 -- resets to 0 because there's no match at the specified index
注意: dotAll
属性与通配符 ( .
) 元字符一起使用。因此,您将在元字符章节中详细了解它的工作原理。此外, hasIndices
还可以用于捕获。因此,您将在分组和捕获章节中了解如何使用它。
使用正则表达式的字符串方法
JavaScript 提供了一些处理字符串的内置方法。其中一些方法将正则表达式作为参数。这些方法包括 match()
、 matchAll()
、 replace()
、 replaceAll()
、 split()
和 search()
. 让我们一一看看。
search()
方法
search()
方法在字符串中搜索正则表达式的匹配项并返回匹配项的索引。
js
const myStr =
"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /freeCodeCamp/;
const searchFCC = myStr.search(re);
console.log(searchFCC); //28
如果 search()
方法找不到匹配项,则返回 -1
:
js
const myStr =
"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /FCC/;
const searchFCC = myStr.search(re);
console.log(searchFCC); //-1
您可能会认为将 g
标志与模式一起使用会返回所有匹配项的索引,但事实并非如此。 g
标志不会影响 search()
方法:
ini
const myStr =
"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /freeCodeCamp/g; //pattern with g flag
const searchFCC = myStr.search(re);
console.log(searchFCC); //28
如果你想获取所有匹配的索引,你应该使用 match()
或 matchAll()
方法。
match()
方法
match()
方法允许您指定正则表达式模式作为参数,然后它遍历您使用它的字符串,并返回一个包含与正则表达式模式匹配的子字符串的数组。
js
const my_str = 'freeCodeCamp';
match = my_str.match(/free/);
console.log(match); // [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]
您还可以将正则表达式模式分离到一个单独的变量中:
js
const my_str = 'freeCodeCamp';
const re = /free/;
const match = my_str.match(re);
console.log(match); // [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]
如果 match()
找到多个匹配项,它会返回数组中的所有匹配项,前提是您在模式中使用 g
标志:
js
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
const match = my_str.match(re);
console.log(match); // ['free', 'free', 'free']
如果扩展数组,则如下所示:
由于结果是一个数组,您可能应该使用 console.table()
而不是 console.log()
,这样您就可以看到匹配的索引:
js
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
const match = my_str.match(re);
console.table(match);
如果 match()
方法找不到匹配项,则返回 null
:
js
const my_str = 'freeCodeCamp';
const re = /ref/;
const match = my_str.match(re);
console.log(match); // null
matchAll()
方法
matchAll()
是 match()
方法的混合体。它返回与您提供的正则表达式匹配的所有子字符串的迭代器。这意味着您必须将其与 global
( g
) 标志一起使用。
因为它返回所有匹配项的迭代器,所以 matchAll()
是循环遍历正则表达式匹配项的绝佳选择。
迭代正则表达式匹配的另一种方法是使用 exec()
方法和 g
标志,然后以这种方式使用 while
循环进行循环:
js
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
let match;
while ((match = re.exec(my_str))) {
console.log(match[0]); //
}
// free
// free
// free
使用 matchAll()
方法,您不需要 exec()
和 while
循环。您只需要一个 for...of
循环来获取匹配项:
js
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
const matches = my_str.matchAll(re);
console.log(matches); // RegExpStringIterator {}
//loop through the matches with a for...of loop
for (const match of matches) {
console.log(match);
}
这将返回每个 match
、它们的索引、测试字符串、长度以及各自数组中的组:
您可以修改控制台日志以仅获取匹配项及其索引:
js
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
const matches = my_str.matchAll(re);
console.log(matches); // RegExpStringIterator {}
//loop through the matches with a for...of loop
for (const match of matches) {
console.log(`Found a match ${match[0]} at index ${match.index}`);
}
/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/
您还可以使用 Array.from()
方法执行相同的操作:
javascript
const my_str =
"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today.";
const re = /free/g;
Array.from(my_str.matchAll(re), (match) =>
console.log(`Found a match ${match[0]} at index ${match.index}`)
);
/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/
如果 matchAll()
方法找不到匹配项,则返回一个空迭代器。如果您决定循环遍历该空迭代器,则控制台中将看不到任何内容。
replace()
方法
replace()
方法的作用正如其名称所暗示的那样。它在字符串中搜索指定字符串或正则表达式的匹配项,并将其替换为指定的替换字符串。它返回一个应用了替换的新字符串。
replace()
方法不像 match()
和 matchAll()
那样简单,因为它接受两个参数 - 正则表达式和替换字符串。然后,测试字符串中与正则表达式匹配的任何子字符串都将替换为替换字符串。
如果正则表达式不包含全局 ( g
) 标志,则仅替换第一个匹配项:
js
const myStr =
'Elephants are very large animals. They are large to the extent that they can uproot a large tree.';
const re = /large/;
const replaceLarge = myStr.replace(re, 'massive');
console.log(replaceLarge); // Elephants are very massive animals. They are large to the extent that they can uproot a large tree.
如果您在模式中使用 g
标志,则所有匹配项都会被替换:
js
const myStr =
'Elephants are very large animals. They are large to the extent that they can uproot a large tree.';
const re = /large/g;
const replaceLarge = myStr.replace(re, 'massive');
console.log(replaceLarge); // Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.
replaceAll()
方法
replaceAll()
方法相对较新,因为它在 ECMAScript 2021 中可用。它是 replace()
的混合体。 replace()
和 replaceAll()
都通过将正则表达式和替换字符串作为参数来执行相同的操作,并用指定的替换字符串替换所有匹配项。
但与 replace()
不同,如果您不使用 g
标志,则只会替换第一个匹配项, replaceAll()
默认情况下会替换所有匹配项:
js
const myStr =
'Elephants are very large animals. They are large to the extent that they can uproot a large tree.';
const re = /large/g;
const replaceLarge = myStr.replaceAll(re, 'massive');
console.log(replaceLarge); // Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.
如果您不将 g
标志与 replaceAll()
一起使用,则会抛出 TypeError
:
js
const myStr =
'Elephants are very large animals. They are large to the extent that they can uproot a large tree.';
const re = /large/;
const replaceLarge = myStr.replaceAll(re, 'massive');
console.log(replaceLarge); // Uncaught TypeError: String.prototype.replaceAll called with a non-global RegExp argument
// at String.replaceAll (<anonymous>)
split()
方法
split()
方法接受一个字符串或正则表达式,并根据您传递给它的字符串或正则表达式将您使用它的字符串拆分为一个数组。 split()
方法还采用可选的 limit
参数,即正数。当您指定 limit
时,分割将在该限制处停止。
无论 split()
在哪里找到匹配项,它都会在数组中创建一个新项目。它的工作原理如下:
js
const myStr = "Codes don't lie. You're the one doing something wrong.";
const re = /\s/; // "\s" means white space - spacebar, backspace, tab, ENTER.
const splitedStr = myStr.split(re);
console.log(splitedStr);
/*
Output:
[
'Codes', "don't",
'lie.', "You're",
'the', 'one',
'doing', 'something',
'wrong.'
]
*/
以下是如何使用带有 limit
参数的 split()
方法:
js
const myStr = "Codes don't lie. You're the one doing something wrong.";
const re = /\s/; // "\s" means white space - spacebar, backspace, tab, ENTER.
const splitedStr = myStr.split(re, 5); // 5 is the limit here
console.log(splitedStr);
/*
output: [ 'Codes', "don't", 'lie.', "You're", 'the' ]
*/
如何匹配 JavaScript 正则表达式中的文字字符
正如我之前指出的,文字字符是您将按原样编写模式的文本或字符串。
如果您想匹配文本 hello
,则 /hello/
应该是您的模式。然后,您可以使用 i
标志来匹配 hello
和 Hello
:
js
const testString = 'hello';
const re = /hello/;
const re2 = /hello/i;
console.log(re.test(testString)); // true
console.log(re2.test(testString)); // true
如果你想匹配 freeCodeCamp
,模式应该就是这样。您还可以创建在任何情况下都匹配 freeCodeCamp
的模式:
js
const testString = 'freeCodeCamp';
const re = /freeCodeCamp/;
const re2 = /freeCodeCamp/i; // match freeCodeCamp in any case
console.log(re.test(testString)); // true
console.log(re2.test(testString)); // true
您还可以使用文字字符来匹配数字:
js
const num = 10234;
const re = /2/;
console.log(re.test(num)); //true
如何在 JavaScript 正则表达式中使用字符集
提醒一下,字符集是用方括号括起来的一组字符。它们提供了一种指定一组字符的方法,正则表达式引擎可以根据这些字符来匹配测试字符串中特定位置的单个字符。
字符集允许您指定字符范围、单个字符或两者的组合。 以下是正则表达式中流行字符集的常见示例:
[abc]
:匹配a
、b
或c
[aeiou]
:匹配任何元音字符[a-z]
:匹配从a
到z
的任何小写字母[A-Z]
:匹配从A
到Z
的任何大写字母 -[0-9]
:匹配 0 到 9 之间的任意数字
我们来看看如何在 JavaScript 正则表达式中匹配上述各个字符集:
js
// uppercase character set
const hcaseRe = /[A-Z]/;
const hcaseStr = 'freeCodeCamp is cool';
console.log(hcaseRe.test(hcaseStr)); //true
// vowels character set
const vowelsRe = /[aeiou]/;
const vowelsStr = 'Imagine how pronunciation would have been without vowels';
console.log(vowelsRe.test(vowelsStr)); //true
// [abc] character set
const abcSetRe = /[abc]/;
const abcSetStr = 'freeCodeCamp is totally free';
console.log(abcSetRe.test(abcSetStr)); //true
// number character set
const numRe = /[0-9]/;
const numStr = 'Thank God for Arabic numerals 0 to 9.';
console.log(numRe.test(numStr)); //true