国外课栈 - 跨学科知识视角栈

正则表达式

 二维码 36
文章附图

所有例子

  • 现在,加载文件会加载到textarea中-源代码
  • 实时ACE编辑器的Regex基础知识-源代码
  • 查找双字—源代码
  • 使用replace将元音加倍-源代码
  • 用户的正则表达式-源代码
  • 索引链接-源代码
  • 随机表达式生成器—源代码,幸亏randexp.js。
  • 拆分和重建文本-源代码
  • 使用回调替换-源代码

相关参考

  • 第1章,掌握正则表达式
  • JavaScript正则表达式指南
  • Eloquent JavaScript正则表达式
  • 正规解释-一种可视化正则表达式的工具
  • 玩正则表达式填字游戏!
  • RegExr –正则表达式游乐场

正则表达式

正则表达式是描述或匹配给定数量文本的字符序列。 例如,序列bob(被视为正则表达式)将匹配另一个文本中出现的单词“ bob”。 以下是对正则表达式基础知识的基本介绍,并在文中探索不同的文本处理应用程序时学习更高级的技术。

关于这个主题写的一本真正精彩的书是:Jeffrey Friedl撰写的Mastering Regular Expressions。我可能建议至少阅读第1章。

正则表达式(简称“ regex”)同时具有文字字符和元字符。在bob中,所有三个字符都是文字,即“ b”要匹配“ b”,“ o”要匹配“ o”,等等。我们也可能有正则表达式:^bob

在这种情况下,^是一个元字符,即它不希望与字符“ ^”匹配,而是表示“一行的开头”。换句话说,上述正则表达式将在以下位置找到匹配项:

bob goes to the park.

但在以下位置找不到匹配项:

jill and bob go to the park.

以下是一些入门的常用元字符(我在下面列出了它们,因为它们会出现在JavaScript正则表达式中,可能与其他语言或环境略有不同):

单字符元字符:

.     any one character
\d   
any digit from 0 to 9
\w   
any word character (a-z,A-Z,0-9)
\W   
any non-word character
\s   
any whitespace character
      (
tab, new line, form feed, end of line, carriage return)
\S   
any non whitespace character

位置元字符:

^     beginning of line
$     
end of line
\b   
word boundary
\B    a non
word boundary

量词(指其前面的字符):

?         appearing once or not at all
*         appearing zero or more times
+         appearing one
or more times
{min,max} appearing within the specified range

使用以上内容,我们可以举出一些简单的示例:

  • ^ $-匹配行首,然后匹配行尾,即匹配任何空白行!
  • ing \ b-匹配“ ing”后跟单词边界,即任何时候在单词的末尾出现“ ing”

字符类在各个字符中用作一种声明,并用方括号括起来的字符表示,即[aeiou]表示与任何元音匹配。 使用^会否定字符类,即[^ aeiou]表示匹配不是元音的任何字符(请注意,这不仅限于字母,它实际上表示的不是a,e,i,o或 u。)连字符表示一个字符范围,例如[0-9]或[az]。

另一个关键的元字符是|,表示或。这就是交替的概念。

John | Jon 表示匹配“ John”或“ Jon”

注意:此正则表达式也可以写为Joh?n,表示与“ Jon”的“ o”和“ n”之间的选项“ h”匹配。

括号也可以用于约束交替。 例如,(212 | 646 | 917)\ d *匹配任何零个或多个数字的序列,后跟212、646或917。 请注意,此正则表达式需要进行改进以考虑空格和/或标点符号。

括号还可以用于捕获组进行反向引用。例如,检查以下正则表达式:\b([0-9A-Za-z]+)s+\1\b。

括号中表达式的第一部分显示为:\ b([0-9A-Za-z] +)表示匹配包含至少一个或多个字母/数字的任何“单词”。下一部分\ s +表示至少一个空格的任何序列。第三部分\ 1表示匹配包含在第一组括号内的任何匹配项,即([0-9A-Za-z] +)。因此,仔细考虑一下,此正则表达式在下一行中将匹配什么?

This is really really super super duper duper fun. Fun!

使用Atom Editor测试正则表达式

一种测试正则表达式的快速方法是使用Atom文本的“查找”。按下⌘F后,只需启用正则表达式选项(用.*按钮指示)即可。

Aa选项使正则表达式不区分大小写。让我们看看其他例子

匹配的网址:http:// [^ \ s <>“'] +

检查此正则表达式

这是另一个正则表达式示例,该示例使用向后引用匹配所有重复的单词\ b(\ w +)\ s + \ 1 \ b。

20200201

(请注意,在上面的示例中,元字符\ b表示“单词边界”,即单词的开头或结尾。)如果不检查单词边界,则正则表达式(\ w +)\ s + \ 1将匹配“ This is”例如。

在Sublime Text中用正则表达式查找/替换也非常有用。例如,您可以按照以下方法将[name](链接)格式的所有markdown网址更改为html <a href="link">名称</a>。

JavaScript中的正则表达式

在JavaScript中,正则表达式(例如字符串)是对象。例如,可以这样创建一个正则表达式对象:

var regex = new RegExp('aregex');

尽管以上内容在技术上是正确的(有时是必要的,我们稍后会介绍),但在JavaScript中创建正则表达式的更常见方法是使用正斜杠。 字符串是引号之间的字符数组,而正则表达式是正斜杠之间的字符数组。 例如:

var regex = /aregex/;

RegExp对象具有几种方法。您可能要尝试的第一件事是test()函数,它根据传入的字符串是否与正则表达式匹配而返回true或false。例如,这可以用于验证电子邮件地址。

var email = /\w+@\w+\.(net|com|edu|org)/;
if (email.test("daniel@shiffman.net")) {
   console.
log("That's a valid e-mail!");
}

JavaScript String对象还具有几种接受正则表达式作为输入的方法。例如search()是一个与indexOf()类似的功能。它查找正则表达式匹配项并返回该匹配项的索引。

var zipcode = "My zip code is 90210";
var index = zipcode.search(/\d{5}/);
console.log(
"The zip code is at index: " + index);

最有用的正则表达式方法可能是match()。 match()是String对象的一种方法,该方法返回正则表达式的匹配项。

var txt = "This is a test.";    // The String the search in
var regex = /test/;             // The regex   
var results = txt.match(regex); // Execute the search

结果现在包含以下数组:

[ 'test' ]

如果正则表达式包含捕获括号,则组也将出现在数组中。例如,假设您需要一个正则表达式来匹配电话号码和字符串。

var txt = 'Phone numbers: 212-555-1234 and 917-555-4321 and 646.555.9876.';   
var regex = /(\d+)[-.]\d+[-.]\d+/;               
var results = txt.match(regex);

上面的不一定是与电话号码匹配的最大正则表达式,但在此示例中将如此。 一个或多个数字后跟一个破折号或句点,然后是一个或多个数字,再次是一个破折号或句点以及一个或多个数字。 让我们看一下结果数组。

[ '212-555-1234', '212' ]

请注意,完整的电话号码匹配是如何显示为第一个(索引0)元素,然后是捕获的组(区号)。 但是,您可能会注意到,原始输入String中有三个电话号码,而match()仅与第一个匹配。 为了找到所有匹配项,我们需要添加其他几个步骤。

在单个匹配的情况下,exec()函数的作用与match()相同。 exec()函数,即使带有全局标志,仍将仅返回第一个匹配项。 但是,如果您使用相同的正则表达式和输入字符串再次调用exec(),它将继续运行并返回第二个匹配项的结果(如果没有匹配项,则返回null。)因此,您可以编写while循环来保持 检查直到结果为空。

var text = 'Phone numbers: 212-555-1234 and 917-555-4321 and 646.555.9876.';   
var regex = /(\d+)[-.]\d+[-.]\d+/g;               
var results = regex.exec(text);

while (results != null) {
   
// do something with the matched results and then

   
// Check again
   results = regex.exec(text);
}

这也可以用下面的速记来写(但是,此处链接的示例使用了较长的代码以保持清晰。)

while (var results = regex.exec(text)) {
   
// do something with the matched results
}

用正则表达式拆分

现在,我可以回顾关于p5的split()和splitTokens()函数的讨论,并看看正则表达式如何使用原生String split()方法作为分隔符。 在这种情况下,字符串会从该正则表达式的每次匹配处开始,分成多个子字符串数组。 这是一个简单的示例,快速计算单词的数量(无论如何都不算完美)。

var text = "This text has characters, spaces, and some punctuation.";
// one or more non-word chars (anything not a-z0-9)
var regex = /\W+/;

var words = text.split(regex);
console.log('Total words: ' + words.length);

单词数组现在包含:

[ 'This',
   
'text',
   
'has',
   
'characters',
   
'spaces',
   
'and',
   
'some',
   
'punctuation'
]

但是,如果您想包括所有定界符怎么办?为此,只需将定界符括在括号中即可。使用var regex = /(\ W +)/;因此您将获得以下结果。

[ 'This',
   ' ',
   
'text',
   ' ',
   
'has',
   ' ',
   
'characters',
   ', ',
   
'spaces',
   ', ',
   
'and',
   ' ',
   
'some',
   ' ',
   
'punctuation',
   
'.',
   '' ]

搜索和替换

运行搜索和替换是使用正则表达式可以执行的功能更强大的功能之一。 这可以通过String的replace()方法完成。 该方法接收两个参数,一个正则表达式和一个替换字符串。 只要有正则表达式匹配项,它就会被提供的字符串替换。

var text = 'Replace every time the word "the" appears with the word ze.';

// \b is a word boundary
// You can think of this as an invisible boundary
// between a non-word character and a word character.
var regex = /\bthe\b/g;   

var replaced = text.replace(regex,'ze');

结果是:

Replace every time ze word "ze" appears with ze word ze.

我们还可以使用对替换字符串中捕获的组的反向引用来引用匹配的文本。对第一个组的反向引用指示为$ 1,第二个为$ 2,依此类推。

var text = "Double the vowels.";
var regex = /([aeiou]+)/g;
var replaced = text.replace(regex, '$1$1');

结果是:

Dououblee thee vooweels

replace()函数还允许您传递一个回调,您可以在其中编写自己的代码并返回替换正则表达式的任何给定匹配项的文本。 这提供了极大的灵活性和功能,因为替换文本的逻辑可以用代码编写,而不是简单地编码为字符串。 假设您有一些文字:

var txt = "This is some text with words of variable length."

然后,您可以调用replace()来搜索正则表达式(以下内容与3-5个字符长的任何单词匹配),并将函数调用作为第二个参数传递。

var output = txt.replace(/\b[a-z]{4,6}\b/gi, replacer);

回调将执行多次,与正则表达式匹配的次数相同。回调将接收匹配的文本作为参数,并将其替换为您返回的内容。

function replacer(match) {
   
var len = match.length;
   
// Four letter words become uppercase
   
if (len == 4) {
   
return match.toUpperCase();
   
// Five letter words become "five"
   }
else if (len == 5) {
   
return "five";
   
// Six letter words turn into today's date
   }
else if (len == 6) {
   
return Date();
   }
}

原始文本现在显示为:

THIS is SOME TEXT WITH five of variable Mon Sep 19 2016 13:59:22 GMT-0400 (EDT).

上面的结果是愚蠢且荒谬的,但是它显示了当您可以在replace()回调中执行任何逻辑并调用任何其他函数(查询API?)时可能发生的事情。

点击获取视频内容+代码

文章分类: 编程技艺Javascript