【DailyENJS第6期】JavaScript正则表达式实用指南

DailyENJS 致力于翻译优秀的前端英文技术文章,为技术同学带来更好的技术视野。

image

当你第一次遇到正则表达式时,它们看起来像是随意的乱码。虽然它们可能看起来不容易理解,但它们也非常有用。

事实上正确理解正则表达式将使你成为一个更加高效的程序员。为了完全理解正则表达式,您首先需要学习基础知识。

什么是正则表达式

正则表达式是一种描述字符串数据中的模式的方法。它们构成了自己的一种小语言,它是许多编程语言的一部分,如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

让我们看一看发生了什么。

  1. 如果我们想强制匹配整个字符串,我们可以添加量词^和。插入符号^匹配输入字符串的开头,而美元符号匹配结尾。因此,如果字符串包含超过10位数,则不匹配

  2. \d 匹配数字字符串

  3. {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

让我们看一看发生了什么。

  1. 同样,我们将整个正则表达式包装在^和$中,以便匹配整个字符串。
  2. ( 开始第一个子表达式
  3. \d{1,2} 匹配智商一个数字最多两个数字
  4. - 匹配连字符
  5. ) 第一个子表达式的结尾
  6. {2} 精确匹配第一个子表达式2次
  7. \d{2} 精确匹配两个数字字符
  8. (\d{2})? 精确匹配两个数字并且是可选的

结论

正则表达式有时可能相当复杂,但正确理解上述概念将有助于您轻松理解更复杂的正则表达式模式。
您可以在此处 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions 了解有关正则表达式的更多信息并可以在此处 https://www.hackerrank.com/domains/regex 练习。

最后照旧是一个广告贴,最近新开了一个分享技术的公众号,欢迎大家关注👇(目前关注人数可怜🤕)

image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,136评论 0 9
  • 9.19--9.23 第7章 正则表达式 正则表达式是一个拆分字符串并查询相关信息的过程。 推荐练习网站: js ...
    如201608阅读 1,015评论 0 4
  • 几个正则表达式编辑器 Debuggex :https://www.debuggex.com/ PyRegex:ht...
    没技术的BUG开发攻城狮阅读 4,581评论 0 23
  • 古书有言:“天地之气,暖则生,寒则杀,性气清冷者,受享亦凉薄,唯和气热心之人,其福亦厚,其泽亦长。”看清一个人的人...
    鑫哥独特阅读 238评论 0 2
  • 我们学校开了一门课,叫做:“国故新知-科学走进人文”。选课的时候,我看到里面内容包络万象,既有国学,又有科学。早些...
    落叶之上阅读 313评论 3 2