JavaScript的正则表达式

314 阅读4分钟

正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于** RegExp** 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法。

创建正则表达式的方法

你可以使用以下两种方法之一构建一个正则表达式:

1、使用一个正则表达式字面量,其由包含在斜杠之间的模式组成,如下所示:

/*
   /pattern/flags
*/
const regex = /ab+c/;
const regex = /^[a-zA-Z]+[0-9]*\W?_$/gi;

在加载脚本后,正则表达式字面值提供正则表达式的编译。当正则表达式保持不变时,使用此方法可获得更好的性能。

2、或者调用RegExp对象的构造函数,如下所示:

/* 
    new RegExp(pattern [, flags])
*/
let regex = new RegExp("ab+c");
let regex = new RegExp(/^[a-zA-Z]+[0-9]*\W?_$/, "gi");
let regex = new RegExp("^[a-zA-Z]+[0-9]*\\W?_$", "gi");

使用构造函数提供正则表达式的运行时编译。使用构造函数,当你知道正则表达式模式将会改变,或者你不知道模式,并从另一个来源,如用户输入。

正则表达式的模式

下面的表格列出了一个我们在正则表达式中可以利用的特殊字符的完整列表和描述。

使用正则表达式

正则表达式可以被用于RegExp的exec和test方法以及 String的match、replace、search和split方法。

当你想要知道在一个字符串中的一个匹配是否被找到,你可以使用test或search方法;想得到更多的信息(但是比较慢)则可以使用exec或match方法。如果你使用exec或match方法并且匹配成功了,那么这些方法将返回一个数组并且更新相关的正则表达式对象的属性和预定义的正则表达式对象(详见下)。如果匹配失败,那么exec方法返回null(也就是false)。

使用括号的子字符串匹配

一个正则表达式模式使用括号,将导致相应的子匹配被记住。例如,/a(b)c /可以匹配字符串“abc”,并且记得“b”。回调这些括号中匹配的子串,使用数组元素[1],……[n]。

使用括号匹配的子字符串的数量是无限的。返回的数组中保存所有被发现的子匹配。下面的例子说明了如何使用括号的子字符串匹配。

下面的脚本使用replace()方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$1,$2表示第一个和第二个括号的子字符串匹配。

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr);

这个表达式输出 "Smith, John"。

通过标志进行高级搜索

正则表达式有四个可选参数进行全局和不分大小写搜索。这些参数既可以单独使用也可以一起使用在任何顺序和包含正则表达式的部分中。

包含一个标志的正则表达式,使用这个表达式:

var re = /pattern/flags;

或者

var re = new RegExp("pattern", "flags");

值得注意的是,标志是一个正则表达式的一部分,它们在接下来的时间将不能添加或删除。

例如,re = /\w+\s/g 将创建一个查找一个或多个字符后有一个空格的正则表达式,或者组合起来像此要求的字符串。

var re = /\w+\s/g;
var str = "fee fi fo fum";
var myArray = str.match(re);
console.log(myArray);

这段代码将输出 ["fee ", "fi ", "fo "]。在这个例子中,你可以将:

var re = /\w+\s/g;

替换成:

var re = new RegExp("\\w+\\s", "g");

并且能获取到相同的结果。

m标志用于指定多行输入字符串应该被视为多个行。如果使用m标志,^和$匹配的开始或结束输入字符串中的每一行,而不是整个字符串的开始或结束。

例子

改变输入字符串的顺序

以下例子解释了正则表达式的构成和string.split() 以及 string.replace()的用途。它会整理一个只有粗略格式的含有全名(名字首先出现)的输入字符串,这个字符串被空格、换行符和一个分号分隔。最终,它会颠倒名字顺序(姓氏首先出现)和list的类型。

// 下面这个姓名字符串包含了多个空格和制表符,
// 且在姓和名之间可能有多个空格和制表符。
var names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ";

var output = ["---------- Original String\n", names + "\n"];

// 准备两个模式的正则表达式放进数组里。
// 分割该字符串放进数组里。

// 匹配模式:匹配一个分号及紧接其前后所有可能出现的连续的不可见符号。
var pattern = /\s*;\s*/;

// 把通过上述匹配模式分割的字符串放进一个叫做nameList的数组里面。
var nameList = names.split(pattern);

// 新建一个匹配模式:匹配一个或多个连续的不可见字符及其前后紧接着由
// 一个或多个连续的基本拉丁字母表中的字母、数字和下划线组成的字符串
// 用一对圆括号来捕获该模式中的一部分匹配结果。
// 捕获的结果稍后会用到。
pattern = /(\w+)\s+(\w+)/;

// 新建一个数组 bySurnameList 用来临时存放正在处理的名字。
var bySurnameList = [];

// 输出 nameList 的元素并且把 nameList 里的名字
// 用逗号接空格的模式把姓和名分割开来然后存放进数组 bySurnameList 中。
//
// 下面的这个替换方法把 nameList 里的元素用 $2, $1 的模式
// (第二个捕获的匹配结果紧接着一个逗号一个空格然后紧接着第一个捕获的匹配结果)替换了
// 变量 $1 和变量 $2 是上面所捕获的匹配结果。

output.push("---------- After Split by Regular Expression");

var i, len;
for (i = 0, len = nameList.length; i < len; i++){
  output.push(nameList[i]);
  bySurnameList[i] = nameList[i].replace(pattern, "$2, $1");
}

// 输出新的数组
output.push("---------- Names Reversed");
for (i = 0, len = bySurnameList.length; i < len; i++){
  output.push(bySurnameList[i]);
}

// 根据姓来排序,然后输出排序后的数组。
bySurnameList.sort();
output.push("---------- Sorted");
for (i = 0, len = bySurnameList.length; i < len; i++){
  output.push(bySurnameList[i]);
}

output.push("---------- End");

console.log(output.join("\n"));

用特殊字符检验输入

在以下例子中,我们期望用户输入一个电话号码。当用户点击“Check”按钮,我们的脚本开始检查这些数字是否合法。如果数字合法(匹配正则表达式所规定的字符序列),脚本显示一条感谢用户的信息并确认该数字。如果这串数字不合法,脚本提示用户电话号码不合法。.

包含非捕获括号 (?: 这个正则表达式寻找三个数字字符\d{3} 或者 | 一个左半括号(跟着三位数字\d{3}, 跟着一个封闭括号 ), (结束非捕获括号 )), 后跟着一个短破折号或左斜杠或小数点,随后跟随三个数字字符,当记忆字符 ([-/.])捕获并记住,后面跟着三位小数 \d{3},再后面跟随记住的左斜杠、右斜杠或小数点 \1,最后跟着四位小数 \d{4}。

当用户按下Enter设置RegExp.input,这些变化也能被激活。

<!DOCTYPE html>
<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
    <meta http-equiv="Content-Script-Type" content="text/javascript">  
    <script type="text/javascript">  
      var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}/;  
      function testInfo(phoneInput) {  
        var OK = re.exec(phoneInput.value);  
        if (!OK)  
          window.alert(phoneInput.value + ' isn\'t a phone number with area code!');  
        else
          window.alert('Thanks, your phone number is ' + OK[0]);  
      }  
    </script>  
  </head>  
  <body>  
    <p>Enter your phone number (with area code) and then click "Check".
        <br>The expected format is like ###-###-####.</p>
    <form action="#">  
      <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Check</button>
    </form>  
  </body>  
</html>

原文链接:developer.mozilla.org/zh-CN/docs/…