0%

javascript-regex-test

javascript-regex-test

简介

javascript中testRegex对象上的一个方法,用来检测字符串是否满足某种规则,举个例子:判断一个字符串中是否包含单词hello

1
2
3
4
5
6
7
8
const regex = new RegExp('hello');
const str = 'hello, world!';

if (regex.test(str)) {
console.log(true);
} else {
console.log(false);
}

简化一下上面的代码,js中正则表达式可以用//包裹,所以可以写成:

1
2
3
const regex = /hello/;
const str = 'hello, world!';
console.log(regex.test(str)); // true

再简化一下,甚至可以写成一行:

1
console.log(/hello/.test('hello, world!')); // true

规则:regex.test(str), 这个表达式中,调用者是正则表达式,参数是字符串,返回值是布尔值。

大小写无关的匹配

默认情况下,正则表达式是匹配时是区分大小写的,如果要忽略大小写进行匹配,可以在正则表达式后面加上/i标志。

1
console.log(/hello/i.test('Hello, world!')); // true

多行匹配

默认情况下,正则表达式是单行匹配的,如果要多行匹配,可以在正则表达式后面加上/m标志。

1
2
3
4
5
6
7
const str = `
Hi,
hello,
world.
`;

console.log(/^hello/.test(str)); // false

因为默认情况下,^只匹配字符串的开头,所以上面的代码返回false。如果要多行匹配,可以这样写:

1
2
3
4
5
6
const str = `
Hi,
hello,
world.
`;
console.log(/^hello/m.test(str)); // true

/m表示多行匹配,即使hello不在字符串的首行,也能匹配到。
注意,这里/m真正的含义如下:

  • 如果不加/m^$匹配整个字符串的开头和结尾。
  • 如果加了/m^$匹配每一行的开头和结尾。

以上面代码为例,如果不加/m,则^hello匹配整个字符串的开头,但是整个字符串的开头是Hi,,所以返回false。如果加了/m,则^hello匹配每一行的开头,而第二行的开头是hello,所以返回true

注意, 如果没有给test传递参数,那么test会尝试匹配字符串undefined

1
console.log(/undefined/.test()); // true

全局匹配

默认情况下,test只会匹配第一个满足条件的字符串,如果要全局匹配,可以在正则表达式后面加上/g标志。

注意:你永远不需要在test方法上加/g标志,因为test方法只返回一个布尔值,而不是匹配到的字符串。
使用/g标志会改变正则表达式的lastIndex属性,这个属性会影响到test方法的行为,导致每次test匹配都从lastIndex开始,而不是从字符串的开头开始。

下面的代码中,为何第二次调用test方法返回false呢?

1
2
3
4
5
6
7
const regex = /foo/g;

// lastIndex = 0;
console.log(regex.test('foo')); // true

// lastIndex = 3;
console.log(regex.test('foo')); // false

分析一下:第一次匹配开始之前,lastIndex = 0, 指向字符串开头,第一次匹配成功后,lastIndex = 3, 下一次匹配从则从下标3开始,但是字符串foo长度为3,后面已经没有字符了,所以导致第二次匹配失败!崩溃吗?

/g选项通常用于String.prototype.replace方法。

1
2
3
const str = 'foobarfoo';
console.log(str.replace(/foo/, '')); // barfoo, 只替换了第一个foo
console.log(str.replace(/foo/g, '')); // bar, 替换了所有的foo

javascript中还有一个String.prototype.replaceAll方法,看名字好像会替换所有满足条件的匹配,但是使用这个方法时,必须添加/g标志,否则会报错,真是脱裤子放屁呀!

1
2
3
const str = 'foobarfoo';
console.log(str.replaceAll(/foo/, '')); // TypeError: String.prototype.replaceAll called with a non-global RegExp argument
console.log(str.replaceAll(/foo/g, '')); // bar

References