JavaScript正则表达式入门

JavaScript正则表达式入门

常常用户在一个网页里登录注册帐号时,要输入用户名、手机号、邮箱地址、设置密码等项目。而对于用户输入的用户名是否规范,输入的是否是邮箱地址、密码强度如何等等都可以通过一正则表达式制定相应的规则来验证校检,来实现一个非常复杂的业务逻辑。

在编写处理字符串的程序或网页时,经常有查找符合某些特定规则的字符串的需要。正则表达式就是用于描述这些规则的工具。正则表达式英文全称为(Regular Expression),

创建正则表达式

  • 使用正则表达式字面量

      // 语法: /pattern/flag
      const reg = /at/g; // g可选,代表全局模式,匹配所有含有"at"的字符串
    
  • 使用RegExp对象构造函数,可以实现正则表达模式随时改变,适用于必须在运行时动态生成正则表达式的情形,如用户输入

      // 语法: new RegExp(pattern [, flags]) 
      let regex = new RegExp('ab+c', 'g');
      let regex = new RegExp(/.at/gi);
      
      // str为用户要查询的值,trim()用于去除字符串的前置和后置空格
      let str = document.getElementById('u-input').value.trim(); 
      let re = new RegExp(str, 'g');
    

正则表达式语法

正则表达式必须写在一行中,因为它们不支持注释和空白

一个用来匹配URL的正则表达式如下:

var parseUrl = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;  

var url = "http://www.ora.com:80/goodparts?q#fragment";

var result = parseUrl.exec(url); 
// exec()方法成功匹配字符串的话,则返回一个字符串片段组成的数组

正则表达式对应的结构图(右键新标签看大图)

  • 正则表达式被包围在一对斜杠//中,表示开始符和结束符。
  • 容器:() [] {}
    • ()一对括号为一个捕获组
    • []作为一个字符集合,匹配方括号中的任意字符。
    • {}后缀里面的数字决定这个因子应该被匹配的次数,(/){0,3} 表示/会被匹配0次,或者1~3次。
  • 捕获组与非捕获型组
    • 捕获型组 格式:(. . .) 会复制它所匹配的文本,放到result数组里。
    • 非捕获型组 格式:(?: . . .) 只是匹配文本,不保存到result数组里。如果不需要使用匹配后的文本,通常用非捕获型来替代少量不优美的捕获型分组,因为捕获会有性能上的损失。
  • /^... $/
    • ^$分别置于模式的最前和最后,表示匹配字符串的开始和结束,保证开头和结尾没有多余的内容。
  • ^在不同位置表示不同的意思。
    • 字符类[?#]以开始,表示这个类包含除?#外的所有字符。
    • 位于整个模式字符类的开头,则表示此字符串的开始,只匹配那些从开头就像该字符串(URL)一样的字符串。
  • ?位于前缀和后缀
    • 后缀,如-?表示这个负号是可选的,(...)?表示这个分组是可选的
  • +*
    • 后缀+表示匹配一个或多个,相当{1,}。
    • 后缀*表示匹配0个或多个,相当{0,}。

更多特殊字符用法,见MDN正则表达式中的特殊字符

元字符

像上面阐释那些具有特殊功能的字符

\ / [ ] () { } ? + * | . ^ $

普通字符

除了元字符外,其他均是普通字符可以直接按字面处理使用,当然如果要使用元字符以及一些控制字符如 - (范围像是A-Z,加上转义可以当作负号来用) ,可以通过在其前面加上转义\符号来去除它自身的特殊用途,即使其字面化。值得注意的是,\ 不能前缀不能使字母或数字字面化。

正则表达式筋骨脉络图

主体结构

分支

序列

因子

转义

字符集

字符转义

分组

量词

两个重要方法test()和exec()

regexp.exec(string)

exec()方法在一个指定字符串中搜索匹配,找到返回一个数组,并更新正则表达式兑现的属性。返回的数组完全匹配成功的文本作为第一项,将正则括号里匹配成功的作为数组填充到后面。匹配失败则返回Null。如果只是为了判断是否匹配,则可以使用RexExp.test()或者String.search()。

var matches = /hello \S+/.exec('This is a hello world!');
console.log(matches[0]);  // 'hello world!'

当rexExp带有g标志(全局搜索所有匹配的字符串)时,可以多次执行exec()查找所有匹配,即一个匹配模式在同一个字符串中发生了几次。

regexp.test(string)

test()执行一个检索,如果regexp与string匹配,则返回true,否则返回false。
可用于if条件语句中

function testinput(re, str) {
	if(re.test(str)) {
		// 要执行的语句			
	} else {
		// 要执行的语句		
	}
}

一些例子

因为正则表达式是有关字符串的复杂规则的,所以字符串String的匹配、替换、查找等方法都可以传入正则表达式作为参数,处理正则表达式的方法有regexp.exec、regexp.test、string.match、string.replace、string.search和string.split。

把String对象分割成字符串数组

需求:利用正则表达式分割用户输入的字符,允许一次批量输入多个内容,格式可以为数字、中文、英文等,可以通过用回车,逗号(全角半角均可),顿号,空格(全角半角、Tab等均可)等符号作为不同内容的间隔

// 指定的分隔符
var re = /[-,,、.\s]+/g;  
// 也可以使用Unicode编码表示 re = /[\u002c\uff0c\u3001\s]+/g;
// 可以声明一个空的数组容器
var data = [];
  • 法一:RegExp.protype[@@split]()方法

      // 语法:str.split([separator[,limit]])
      
      // str为用户输入的值
      data = data.concat(str.split(re)); 
    
  • 法二:String.protype.split()

      // 语法:regexp[Symbo.split](str[,limit])
      
      data = data.concat(re[Symbol.split](str));
    

两个方法的使用方法相同,只是this和参数顺序不同。

使用正则表达式匹配实现输入查询

已知存在一个数组data,现在用户输入一个值来查询是否存在某个字符串,匹配到且做一定标识(如颜色的改变)

  • 法一:使用正则表达式reg.test()方法,找到返回true,否则为false。

      data.forEach(function (element, index, array) {
          // str为用户要查询的值
          var re = new RegExp(str, 'g');
    
          // 匹配到的内容则改变背景颜色,没有匹配到的则为默认颜色
          if (re.test(element.innerHTML)) {
              element.style.background = '#49b310';
              element.style.border = '1px solid #ccc';
          } 
          else {
              element.style.background = '#ff3f41';
          }
      });	
    
  • 法二:使用字符串位置方法indexOf()lastIndexOf()方法,找到返回字串首次出现的下标,找不到则返回-1。

      if (data[index].indexOf(str) !== -1) { // 设置标识}
    

正则表达式之空格处理

(更多见维基百科:全角和半角

中文/英文输入法下,按space键分别出全角空格和半角空格。使用转义字符\s可以匹配任何空白符,它等同于[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029],这是Unicode空白的一个不完全子集。

demo

总结

不要复制粘贴,杜绝死记硬背,诚心正意,自证良知,由外入里,层层剖析。
更详细的回答见知乎:你是如何学会正则表达式的?

在线工具

拓展阅读

参考资料

posted @ 2017-09-10 18:15  花森煜米  阅读(683)  评论(0编辑  收藏  举报