讲给前端的正则表达式(2):写出更优雅、更精确的正则表达式[每日前端夜话0x101]
今天,我们回到 JavaScript 中的正则表达式。如果你还是新手,请查看上一篇文章。这次,我们将学习如何编写更优雅的模式并定义搜索字符串的位置。

定义重复的较短方法

我们知道星号 * 可以使表达式匹配 0 次或多次。这相当于{0,}。实际上还有其他更短的形式,使用它们可以使样式更优雅,更短。

一次或多个重复


使用加号 + ,我们可以表示该表达式可能匹配一次或多次。这类似于星号,但在这里必须至少匹配一次。等效于{{1,}。

1/1+23/.test('123'); // true2/1+23/.test('111123'); // true3/1+23/.test('23'); // false

这意味着 /.+/ 匹配至少出现一次的任何字符。

1/.+/.test(''); // false2/.*/.test(''); // true

例如检查一个字符串是否包含另一个子字符串,但是不以它结尾:

1// function checks if the string contains question marks,2// but does not end with it3function hasQuestionMarkBeforeEnd(string) {4  return /\?.+/.test(string);5}67hasQuestionMarkBeforeEnd('Do you know regex yet?'); // false8hasQuestionMarkBeforeEnd('Do you know regex yet? Yes, I do!'); // true

请注意,问号是一个特殊字符,因此我们需要在其前面加一个反斜杠。

可以更进一步,写一个更加通用的函数:

1function containsPatternBeforeEnd(string, pattern) {2  return RegExp(`${pattern}.+`).test(string);3}45containsPatternBeforeEnd('cat, dog', 'cat'); // true6containsPatternBeforeEnd('cat, dog', 'dog'); // false

可选字符


如上所述,问号是一个特殊字符。使用它可以创建带有可选字符的模式。它相当于 {0,1}。

1function wereFilesFound(string) {2  return /[1-9][0-9]* files? found/.test(string);3}45wereFilesFound('0 files found');  // false6wereFilesFound('No files found'); // false7wereFilesFound('1 file found');   // true8wereFilesFound('2 files found');  // true

用较短的方法定义一组可能出现的字符

以前我们使用方括号 [] 来定义一组可能出现的字符。在正则表达式中,你可以参考一些实现的集合。

字母数字字符


如果你想匹配所有字母和数字字符,则需要这样的模式:/[A-Za-z0-9_]/。相当复杂不是吗?不过,有一种更短的方法:\w。请当心:它们都不能匹配任何特定于语言的字符!

非字母数字字符


与上述模式相反:/^[A-Za-z0-9_]/。等价于 \W。它有相同的缺陷,不能处理特定于语言的字符:

 1function isAlphanumeric(string) { 2  return /\w/.test(string); 3}; 4 5function isNotAlphanumeric(string) { 6  return /\W/.test(string); 7}; 8 9isAlphanumeric('Ó'); // false10isNotAlphanumeric('Ó'); // true

处理数字


之前我们了解到要匹配任何数字,我们可以使用类似 [0-9] 的模式。还可以用 \d。它能够匹配任何数字:

1isItADigit(string) {2  return /\d/.test(string);3}45isItADigit('5'); // true6isItADigit('a'); // false

在某些实现中(包括 JavaScript),\d 只表示 [0-9]。在某些情况下,它可以匹配任何 Unicode 数字字符,例如阿拉伯数字。

使用 \D 能够匹配任何非数字字符。

处理空格
在字符串中,有几种类型的空格字符:

  • 空格 ” ”

  • tab “/t”

  • 新行 “\n”

  • 回车符 “\r”

要创建一个匹配所有情况的模式,需要类似这样的复杂内容:/[\t\n\r]/。不过,有一种更简单的方法,它涉及使用 \s(小写s):

1function containsWhitespace(string) {2  return /\s/.test(string);3}45containsWhitespace('Lorem ipsum'); // true6containsWhitespace('Lorem_ipsum'); // false

另外 \S (大写S)可以匹配任何非空白字符。

指定位置

到目前为止,只是在写单纯可以在字符串中进行匹配的模式。我们还可以指定位置使匹配更精确。

插入符号


如果在模式的开头添加 ^ 符号,则仅当被测试的字符串以该模式开头时,它才会匹配:

1/^dog/.test('dog and cat'); // true2/^dog/.test('cat and dog'); // false

请注意,插入符号用在方括号中时有另外的作用,在上一篇文章中曾说过。

美元符号


在模式的末尾添加一个美元符号,仅当它出现在字符串的末尾时,才会匹配:

1/dog$/.test('dog and cat'); // false2/dog$/.test('cat and dog'); // true

结合两个标志


如果你的模式以 ^ 开头,并以 $ 结尾,则仅当测试的字符串整体匹配时,它才会匹配:

1/success/.test('Unsuccessful operation'); // true2/^success$/.test('Unsuccessful operation'); // false

即使在测试的字符串中可以找到字符串 “success”,将模式包含在 ^ 和 $ 中也会使它仅在整个字符串匹配时才匹配。

再看一个例子:

1function areAllCharactersDigits(string) {2  return /^[0-9]+$/.test(string);3}

这个例子检查字符串是否仅包含数字。使用加号会使它匹配一位或多位数字。如果在字符串的开头到结尾之间有数字,并且没有其他内容,则将模式用 ^ 和 $ 括起来能够确保仅匹配表达式。

1areAllCharactersDigits('123'); // true2areAllCharactersDigits('Digits: 123'); // false

下面的模式能够匹配第二个字符串:

1/[0-9]+/.test('Digits: 123');  // true

多行模式


我们已经了解到可以将其他标志添加到模式中。其中之一是由字母 m 表示的多行标志。它改变了插入符号和美元符号的含义。在多行模式下,它们代表一行的开头和结尾,而不是整个字符串。

1const pets = `2dog3cat4parrot and other birds5`;67/^dog$/m.test(pets); // true8/^cat$/m.test(pets); // true9/^parrot$/m.test(pets); // false

我在这里用了模板字符串添加换行符。还可以这样做:

1const pets = 'dog\ncat\nparrot and other birds';23/^dog$/m.test(pets); // true4/^cat$/m.test(pets); // true5/^parrot$/m.test(pets); // false

由于使用了多行标志,因此是测试了多个行,而不测试了整个字符串。但是你会发现最后的测试仍然无法通过,因为最后一行包含的内容不只是“parrot”。

总结

这次,我们学习了更多的特殊字符,并通过它们用较短的形式编写更复杂的模式。现在你更加了解了匹配模式,从而进一步了解如何指定要查找的样式的位置:字符串的开头与结尾,能够写出能够匹配整个字符串或行(多行模式下)的正则表达式。我们写出的模式将会越来越复杂:我鼓励你多去使用。后续的文章即将推出,请持续关注!

原文:https://wanago.io/2018/05/07/regex-course-part-two-writing-more-elegant-and-precise-patterns/

更多相关文章

  1. 从模版方法模式到 SPI 演变 :好的思想通用而持久
  2. 漫谈设计模式在 Spring 框架中的良好实践
  3. 设计模式之适配器模式
  4. 设计模式之访问者模式
  5. 设计模式之中介者模式
  6. 设计模式之备忘录模式
  7. 设计模式之责任链模式
  8. 设计模式之状态模式
  9. 设计模式之迭代器模式

随机推荐

  1. 记录Golang Recover的一个小坑
  2. 哪些大公司在用go语言
  3. go是什么开发语言
  4. Go语言属于什么语言
  5. go语言常用命令有哪些
  6. go语言有引用传递么
  7. go语言如何导入包
  8. go语言如何改变回显颜色
  9. go语言用什么ide
  10. go语言有什么特点?