DailyENJS 致力于翻译优秀的前端英文技术文章,为技术同学带来更好的技术视野。
当你第一次遇到正则表达式时,它们看起来像是随意的乱码。虽然它们可能看起来不容易理解,但它们也非常有用。
事实上正确理解正则表达式将使你成为一个更加高效的程序员。为了完全理解正则表达式,您首先需要学习基础知识。
什么是正则表达式
正则表达式是一种描述字符串数据中的模式的方法。它们构成了自己的一种小语言,它是许多编程语言的一部分,如Javascript,Perl,Python,Php和Java。
正则表达式能够帮助你去校验字符串,如电子邮件地址或密码。
创建一个正则表达式
在Javascript中有两种方式可以创建正则表达式。可以使用RegExp构造函数创建,也可以使用正斜杠(/)来创建。
使用 RegExp 构造函数
语法: new RegExp(pattern[, flags])
例子:
var regexConst = new RegExp('abc')
使用正则表达式字面量
语法: /pattern/flags
例子:
var regexLiteral = /abc/;
这里的 flags 是可选的,文章的后面将会解释这些。
可能还有一些情况需要动态创建正则表达式,在这种情况下,正则表达式字面量不起作用,因此您必须使用正则表达式构造函数。
无论您选择哪种方法,结果都是正则表达式对象,都有相同的方法和属性。
由于正斜杠用于创建正则表达式,因此如果要将 / 用作正则表达式的一部分,则必须使用反斜杠(\)转义正斜杠(/)。
正则表达式的方法
测试正则表达式主要有两种方法。
RegExp.prototype.test()
这个方法用于测试是否已找到匹配项。它接受一个字符串作为参数,并返回true或false:
例子:
var regex = /hello/;
var str = 'hello world';
var result = regex.test(str);
console.log(result);
// returns true
RegExp.prototype.exec()
这个方法返回包含所有匹配组的数组。它接受一个字符串作为参数。
例子:
var regex = /hello/;
var str = 'hello world';
var result = regex.exec(str);
console.log(result);
// returns [ 'hello', index: 0, input: 'hello world', groups: undefined ]
// 'hello' -> is the matched pattern.
// index: -> Is where the regular expression starts.
// input: -> Is the actual string passed.
我们将在下面使用test()方法。
简单的正则表达式匹配
它是最基本的模式,它简单地将文字文本与测试字符串相匹配。例如:
var regex = /hello/;
console.log(regex.test('hello world'));
// true
特殊字符
到目前为止,我们已经创建了简单的正则表达式。现在,让我们在处理更复杂的情况时充分利用正则表达式的全部功能。
例如,不是匹配特定的电子邮件地址,而是说我们想要匹配许多电子邮件地址。这就是特殊字符发挥作用的地方。为了完全理解正则表达式,您必须记住特殊的符号和字符。
falgs
正则表达式有五个可选的flag或修饰符。让我们讨论两个最重要的flag:
g:全局匹配;找到所有匹配,而不是在第一个匹配后停止
i:忽略大小写
您还可以在单个正则表达式中组合修饰符。并且他们的顺序对结果没有任何影响。
接下来看看一些例子:
使用正则表达式字面量:
var regexGlobal = /abc/g;
console.log(regexGlobal.test('abc abc'));
// it will match all the occurence of 'abc', so it won't return
// after first match.
var regexInsensitive = /abc/i;
console.log(regexInsensitive.test('Abc'));
// returns true, because the case of string characters don't matter
// in case-insensitive search.
使用 RegExp 构造函数:
var regexGlobal = new RegExp('abc','g')
console.log(regexGlobal.test('abc abc'));
// it will match all the occurence of 'abc', so it won't return // after first match.
var regexInsensitive = new RegExp('abc','i')
console.log(regexInsensitive.test('Abc'));
// returns true, because the case of string characters don't matter // in case-insensitive search.
Character groups:
字符集[xyz]-字符集是一种在一个位置匹配不同字符的方法,它匹配括号内的字符中字符串中的任何单个字符。例如:
var regex = /[bt]ear/;
console.log(regex.test('tear'));
// returns true
console.log(regex.test('bear'));
// return true
console.log(regex.test('fear'));
// return false
注: 除了插入符号(^)(在字符集中具有完全不同的含义)之外的所有特殊字符在字符集内(中括号内)都会失去其特殊含义。
否定字符集(Negated character set [^xyz])—— 它匹配括号中未包含的任何内容。例如:
var regex = /[^bt]ear/;
console.log(regex.test('tear'));
// returns false
console.log(regex.test('bear'));
// return false
console.log(regex.test('fear'));
// return true
范围[a-z](Ranges[a-z]): 假设我们想要在一个位置匹配字母表中的所有字母,我们可以在括号内写出所有字母,但有一种更简单的方法,那就是范围。例如:[a-h]将匹配a到h的所有字母。范围也可以是[0-9]之类的数字或[A-Z]之类的大写字母。
var regex = /[a-z]ear/;
console.log(regex.test('fear'));
// returns true
console.log(regex.test('tear'));
// returns true
元字符(Meta-characters) - 元字符是具有特殊含义的字符。有许多元字符,但我将在这里介绍最重要的元字符。
\d:匹配任何数字字符(与[0-9]相同)
\w: 匹配任何单词字符。单词字符是任何字母,数字和下划线。(与[a-zA-Z0-9_]相同)即字母数字字符
\s: 匹配空白字符(空格,制表符等)
\t: 仅匹配制表符
\b: 在单词的开头或结尾找到匹配项。也称为单词边界
.: 匹配除换行符之外的任何字符
\D: 匹配任何非数字字符(与[^ 0-9]相同)
\W: 匹配任何非单词字符(与[^ a-zA-Z0-9_]相同)
\S: 匹配非空白字符
量词: 量词是在正则表达式中具有特殊含义的符号
- +: 匹配前面的表达式1次或多次
var regex = /\d+/;
console.log(regex.test('8'));
// true
console.log(regex.test('88899'));
// true
console.log(regex.test('8888845'));
- *: 匹配前面的表达式0次或更多次
var regex = /go*d/;
console.log(regex.test('gd'));
// true
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// true
- ?: 匹配前面的表达式0或1次,即前面的模式是可选的
var regex = /goo?d/;
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// false
- ^: 匹配字符串的开头。即插入符号(^)匹配字符串的开头。
var regex = /^g/;
console.log(regex.test('good'));
// true
console.log(regex.test('bad'));
// false
console.log(regex.test('tag'));
// false
- )符号与字符串的结尾匹配。
var regex = /.com$/;
console.log(regex.test('test@testmail.com'));
// true
console.log(regex.test('test@testmail'));
// false
- {N}: 完全匹配前面表达式N次
var regex = /go{2}d/;
console.log(regex.test('good'));
// true
console.log(regex.test('god'));
// false
- {N,}: 匹配前面正则表达式至少N次
var regex = /go{2,}d/;
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// true
console.log(regex.test('gooood'));
// true
- {N,M}: 匹配前面正则表达式至少N次且最多M次(其中M> N)
var regex = /go{1,2}d/;
console.log(regex.test('god'));
// true
console.log(regex.test('good'));
// true
console.log(regex.test('goood'));
// false
Alternation X|Y: 匹配X或Y,例如:
var regex = /(green|red) apple/;
console.log(regex.test('green apple'));
// true
console.log(regex.test('red apple'));
// true
console.log(regex.test('blue apple'));
// false
注意 - 如果要将任何特殊字符用作表达式的一部分,例如,您希望匹配文字+或。,则必须使用反斜杠(\)对其进行转义。
例如:
var regex = /a+b/; // This won't work
var regex = /a\+b/; // This will work
console.log(regex.test('a+b')); // true
高级
(x): 匹配x并记住这个匹配。这些被称为捕获组。这也用于在正则表达式中创建子表达式。例如 :
var regex = /(foo)bar\1/;
console.log(regex.test('foobarfoo'));
// true
console.log(regex.test('foobar'));
// false
\1
记住并使用括号内第一个子表达式匹配。
(?:x): 匹配x并且不记得匹配。这些被称为非捕获组。这里 \1
不起作用,它将匹配文字 \1
var regex = /(?:foo)bar\1/;
console.log(regex.test('foobarfoo'));
// false
console.log(regex.test('foobar'));
// false
console.log(regex.test('foobar\1'));
// true
x(?=y): 仅当x后跟y时才匹配x。也被称为正向先行断言。例如:
var regex = /Red(?=Apple)/;
console.log(regex.test('RedApple'));
// true
在上面的示例中,仅当Redis后跟Apple时才会进行匹配。
正则表达式练习
让我们练习一些我们上面学到的概念。
- 匹配任何10个数字:
var regex = /^\d{10}$/;
console.log(regex.test('9995484545'));
// true
让我们看一看发生了什么。
如果我们想强制匹配整个字符串,我们可以添加量词^和匹配结尾。因此,如果字符串包含超过10位数,则不匹配
\d
匹配数字字符串{10}
匹配前一个表达式,在这种情况下\d
恰好10次。因此,如果测试字符串包含少于或大于10位数,则结果将为false。
- 匹配日期格式DD-MM-YYYY或DD-MM-YY
var regex = /^(\d{1,2}-){2}\d{2}(\d{2})?$/;
console.log(regex.test('01-01-1990'));
// true
console.log(regex.test('01-01-90'));
// true
console.log(regex.test('01-01-190'));
// false
让我们看一看发生了什么。
- 同样,我们将整个正则表达式包装在^和$中,以便匹配整个字符串。
-
(
开始第一个子表达式 -
\d{1,2}
匹配智商一个数字最多两个数字 -
-
匹配连字符 -
)
第一个子表达式的结尾 -
{2}
精确匹配第一个子表达式2次 -
\d{2}
精确匹配两个数字字符 -
(\d{2})?
精确匹配两个数字并且是可选的
结论
正则表达式有时可能相当复杂,但正确理解上述概念将有助于您轻松理解更复杂的正则表达式模式。
您可以在此处 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions 了解有关正则表达式的更多信息并可以在此处 https://www.hackerrank.com/domains/regex 练习。
最后照旧是一个广告贴,最近新开了一个分享技术的公众号,欢迎大家关注👇(目前关注人数可怜🤕)