javascript类型系统_正则表达式RegExp类型详解


Posted in Javascript onJune 24, 2016

前面的话

前面已经介绍过javascript中正则表达式的基础语法。javascript的RegExp类表示正则表达式,String和RegExp都定义了方法,使用正则表达式可以进行强大的模式匹配和文本检索与替换。本文将介绍正则表达式的RegExp对象,以及正则表达式涉及
到的属性和方法

对象

javascript中的正则表达式用RegExp对象表示,有两种写法:一种是字面量写法;另一种是构造函数写法

Perl写法

正则表达式字面量写法,又叫Perl写法,因为javascript的正则表达式特性借鉴自Perl

正则表达式字面量定义为包含在一对斜杠(/)之间的字符,并且可以设置3个标志

var expression = /pattern/flags;

正则表达式的匹配模式支持下列3个标志:

g: 表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止

i: 表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写

m: 表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项

//匹配字符串所有'at'的实例
var p = /at/g;
//test()方法返回一个布尔值表示是否可以找到匹配项
console.log(p.test('ata'));//true
console.log(p.test('aba'));//false

RegExp构造函数

和普通的内置对象一样,RegExp正则表达式对象也支持new+RegExp()构造函数的形式

RegExp构造函数接收两个参数:要匹配的字符串模式(pattern)和可选的标志字符串(flags),标志字符串和字面量的三个标志含义相同:'g'、'i'、'm'

RegExp构造函数的两个参数都是字符串。且使用字面量形式定义的任何表达式都可使用构造函数

//匹配字符串所有'at'的实例
var p1 = /at/g;
//同上
var p2 = new RegExp('at','g');

[注意]ECMAScript3规范规定,一个正则表达式直接量会在执行到它时转换为一个RegExp对象,同一段代码所表示正则表达式直接量的每次运算都返回同一个对象。ECMAScript5规范则做了相反的规定,同一段代码所表示的正则表达式直接量的每次

运算都返回新对象。IE6-8一直是按照ECMAScript5规范的方式实现的,所以并没有兼容性问题

由于正则表达式字面量并不支持变量,所以如果正则表达式中出现变量只能使用RegExp构造函数以字符串拼接的形式,将变量拼接到RegExp构造函数的参数中

【tips】通过类名classname获取元素

function getByClass(obj,classname){
  var elements = obj.getElementsByTagName('*');
  var result = [];
  var pattern = new RegExp( '(^|\\s)'+ classname + '(\\s|$)');
  for(var i = 0; i < elements.length; i++){
    if(pattern.test(elements[i].className)){
      result.push(elements[i]);
    }
  }
  return result;
}

实例属性

每个RegExp实例对象都包含如下5个属性

global:  布尔值,表示是否设置了g标志
ignoreCase: 布尔值,表示是否设置了i标志
lastIndex:  整数,表示开始搜索下一个匹配项的字符位置,从0算起
multiline:  布尔值,表示是否设置了标志m
source: 
 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
var pattern = new RegExp('\\[bc\\]at','i');
console.log(pattern.global);//false
console.log(pattern.ignoreCase);//true  
console.log(pattern.multiline);//false
console.log(pattern.lastIndex);//0
console.log(pattern.source);//'\[bc\]at'

如果使用RegExp的exec()或test()函数,并且设定了全局模式'g',正则表达式的匹配就会从lastIndex的位置开始,并且在每欠匹配成功之后重新设定lastIndex。这样,就可以在字符串中重复迭代,依次寻找各个匹配结果。但是,如果需要对不同字符串调用同一个RegExp的exec()或test()方法,这个变量也也可能会带来意料之外的匹配结果,所以在更换字符串时,要显式地将RegExp的lastIndex置为0

//exec()方法以数组形式返回匹配项
var p = /\w/g;
var s = 'ab';
console.log(p.lastIndex);//0
console.log(p.exec(s));//['a']
console.log(p.lastIndex);//1
console.log(p.exec(s));//['b']
console.log(p.lastIndex);//2
console.log(p.exec(s));//null
console.log(p.lastIndex);//0
var p = /\w/g;
var s1 = 'ab';
var s2 = 'ba';
console.log(p.lastIndex);//0
console.log(p.exec(s1));//['a']
console.log(p.lastIndex);//1
console.log(p.exec(s2));//['a']
console.log(p.lastIndex);//2

构造函数属性

RegExp构造函数属性被看成静态属性,这些属性基于所执行的最近一次正则表达式操作而变化

有两种方式访问它们,即长属性名和短属性名。短属性名大都不是有效的ECMAScript标识符,所以必须通过方括号语法来访问它们

长属性名    短属性名    
   说明
input       $_        最近一次要匹配的字符串
lastMatch     $&        最近一次的匹配项
lastParen     $+        最近一次匹配的捕获组
leftContext    $`        input字符串中lastMatch之前的文本
multiline     $*        布尔值,表示是否所有表达式都使用多行模式
rightContext   $'        Input字符串中lastMarch之后的文本

使用这些属性,可以从exec()方法或test()方法执行的操作中提取出更具体的信息

//test()用于测试一个字符串是否匹配某个正则表达式,并返回一个布尔值
var text = 'this has been a short summer';
var pattern = /(.)hort/g;
if(pattern.test(text)){
  console.log(RegExp.input);//'this has been a short summer'
  console.log(RegExp.leftContext);//'this has been a '
  console.log(RegExp.rightContext);//' summer'
  console.log(RegExp.lastMatch);//'short'
  console.log(RegExp.lastParen);//'s'
  console.log(RegExp.multiline);//false
  console.log(RegExp['$_']);//'this has been a short summer'
  console.log(RegExp['$`']);//'this has been a '
  console.log(RegExp["$'"]);//' summer'
  console.log(RegExp['$&']);//'short'
  console.log(RegExp['$+']);//'s'
  console.log(RegExp['$*']);//false    
}

javascript有9个用于存储捕获组的构造函数属性,在调用exec()或test()方法时,这些属性会被自动填充

[注意] 理论上,应该保存整个表达式匹配文本的RegExp.$0并不存在,值为undefined

//RegExp.$1\RegExp.$2\RegExp.$3……到RegExp.$9分别用于存储第一、第二……第九个匹配的捕获组
var text = 'this has been a short summer';
var pattern = /(..)or(.)/g;
if(pattern.test(text)){
  console.log(RegExp.$1);//sh
  console.log(RegExp.$2);//t
}

实例方法 

RegExp对象的实例方法共5个,分为两类。包括toString()、toLocalString()、valueOf()这3种对象通用方法和test()、exec()正则匹配方法

对象通用方法

RegExp对象继承了Object对象的通用方法toString()、toLocaleString()、valueOf()这三个方法

【toString()】

toString()方法返回正则表达式的字面量

【toLocaleString()】

toLocaleString()方法返回正则表达式的字面量

【valueOf()】

valueOf()方法返回返回正则表达式对象本身

[注意]不论正则表达式的创建方式是哪种,这三个方法都只返回其字面量形式

var pattern = new RegExp('[bc]at','gi');
console.log(pattern.toString()); // '/[bc]at/gi'
console.log(pattern.toLocaleString()); // '/[bc]at/gi'
console.log(pattern.valueOf()); // /[bc]at/gi

var pattern = /[bc]at/gi;
console.log(pattern.toString()); // '/[bc]at/gi'
console.log(pattern.toLocaleString()); // '[bc]at/gi'
console.log(pattern.valueOf()); // /[bc]at/gi

正则匹配方法

正则表达式RegExp对象的正则匹配方法只有两个:分别是exec()和test()

【exec()】

exec()方法专门为捕获组而设计,接受一个参数,即要应用模式的字符串。然后返回包含匹配项信息的数组,在没有匹配项的情况下返回null

在匹配项数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串,如果模式中没有捕获组,则该数组只包含一项

返回的数组包含两个额外的属性:index和input。index表示匹配项在字符串的位置,input表示应用正则表达式的字符串

var text = 'mom and dad and baby and others';
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
console.log(pattern,matches);
//pattern.lastIndex:20
//matches[0]:'mom and dad and baby'
//matches[1]:' and dad and baby'
//matches[2]:' and baby'
//matches.index:0
//matches.input:'mom and dad and baby and others'

对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec(),将始终返回第一个匹配项的信息;而在设置全局标志的情况下,每次调用exec()都会在字符串中继续查找新匹配项

var text = 'cat,bat,sat,fat';
var pattern1 = /.at/;
var matches = pattern1.exec(text);
console.log(pattern1,matches);
//pattern1.lastIndex:0
//matches[0]:'cat'
//matches.index:0
//matches.input:'cat,bat,sat,fat'

var text = 'cat,bat,sat,fat';
matches = pattern1.exec(text);  
console.log(pattern1,matches);  
//pattern1.lastIndex:0
//matches[0]:'cat'
//matches.index:0
//matches.input:'cat,bat,sat,fat'
var text = 'cat,bat,sat,fat';
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
console.log(pattern2,matches);  
//pattern2.lastIndex:3
//matches[0]:'cat'
//matches.index:0
//matches.input:'cat,bat,sat,fat'

var text = 'cat,bat,sat,fat';
matches = pattern2.exec(text);
console.log(pattern2,matches);  
//pattern2.lastIndex:7
//matches[0]:'bat'
//matches.index:4
//matches.input:'cat,bat,sat,fat'

【tips】用exec()方法找出匹配的所有位置和所有值

var string = 'j1h342jg24g234j 3g24j1';
var pattern = /\d/g;
var valueArray = [];//值
var indexArray = [];//位置
var temp;
while((temp=pattern.exec(string)) != null){
  valueArray.push(temp[0]);
  indexArray.push(temp.index); 
}
//["1", "3", "4", "2", "2", "4", "2", "3", "4", "3", "2", "4", "1"] [1, 3, 4, 5, 8, 9, 11, 12, 13, 16, 18, 19, 21]
console.log(valueArray,indexArray);

【test()】

test()方法用来测试正则表达式能否在字符串中找到匹配文本,接收一个字符串参数,匹配时返回true,否则返回false

var text = '000-00-000';
var pattern = /\d{3}-\d{2}-\d{4}/;
if(pattern.test(text)){
  console.log('The pattern was matched');
}

同样地,在调用test()方法时,会造成RegExp对象的lastIndex属性的变化。如果指定了全局模式,每次执行test()方法时,都会从字符串中的lastIndex偏移值开始尝试匹配,所以用同一个RegExp多次验证不同字符串,必须在每次调用之后,将lastIndex值置为0

var pattern = /^\d{4}-\d{2}-\d{2}$/g;
console.log(pattern.test('2016-06-23'));//true
console.log(pattern.test('2016-06-23'));//false

//正确的做法应该是在验证不同字符串前,先将lastIndex重置为0
var pattern = /^\d{4}-\d{2}-\d{2}$/g;
console.log(pattern.test('2016-06-23'));//true
pattern.lastIndex = 0;
console.log(pattern.test('2016-06-23'));//true

前面介绍过,javascript有9个用于存储捕获组的构造函数属性,在调用exec()或test()方法时,这些属性会被自动填充

[注意]理论上,应该保存整个表达式匹配文本的RegExp.$0并不存在,值为undefined

if(/^(\d{4})-(\d{2})-(\d{2})$/.test('2016-06-23')){
  console.log(RegExp.$1);//'2016'
  console.log(RegExp.$2);//'06'
  console.log(RegExp.$3);//'23'
  console.log(RegExp.$0);//undefined
}

以上就是小编为大家带来的javascript类型系统_正则表达式RegExp类型详解全部内容了,希望大家多多支持三水点靠木~

Javascript 相关文章推荐
javascript+dom树型菜单类,希望朋友们一起进步
May 03 Javascript
Javascript级联下拉菜单以及AJAX数据验证核心代码
May 10 Javascript
js模拟点击以提交表单为例兼容主流浏览器
Nov 29 Javascript
jQuery操作CheckBox的方法介绍(选中,取消,取值)
Feb 04 Javascript
JS实现表单中checkbox对勾选中增加边框显示效果
Aug 21 Javascript
javascript实现数组去重的多种方法
Mar 14 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
Aug 19 Javascript
详解node服务器中打开html文件的两种方法
Sep 18 Javascript
详解vue-cli官方脚手架配置
Jul 20 Javascript
jQuery中each和js中forEach的区别分析
Feb 27 jQuery
关于vue-cli 3配置打包优化要点(推荐)
Apr 22 Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
Jun 05 Javascript
JQuery DIV 动态隐藏和显示的方法
Jun 23 #Javascript
微信QQ的二维码登录原理js代码解析
Jun 23 #Javascript
再次谈论Javascript中的this
Jun 23 #Javascript
BootStrap使用popover插件实现鼠标经过显示并保持显示框
Jun 23 #Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
Jun 23 #Javascript
Bootstrap弹出带合法性检查的登录框实例代码【推荐】
Jun 23 #Javascript
JS留言功能的简单实现案例(推荐)
Jun 23 #Javascript
You might like
古巴咖啡 Cubita琥爵咖啡 独特的加勒比海风味咖啡
2021/03/06 新手入门
解决了Ajax、MySQL 和 Zend Framework 的乱码问题
2009/03/03 PHP
ajax 的post方法实例(带循环)
2011/07/04 PHP
PHP中如何实现常用邮箱的基本判断
2014/01/07 PHP
PHP实现文件下载断点续传详解
2014/10/15 PHP
PHP中使用imagick实现把PDF转成图片
2015/01/26 PHP
PHP创建PowerPoint2007文档的方法
2015/12/10 PHP
php bootstrap实现简单登录
2016/03/08 PHP
wordpress网站转移到本地运行测试的方法
2017/03/15 PHP
广告代码静态化js通用函数
2007/05/09 Javascript
IE php关于强制下载文件的代码
2008/08/23 Javascript
jQuery Ajax之load()方法
2009/10/12 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
javascript处理table表格的代码
2010/12/06 Javascript
基于javascript滚动图片具体实现
2013/11/18 Javascript
用js读、写、删除Cookie代码分享及详细注释说明
2014/06/05 Javascript
jQuery实现简单下拉导航效果
2015/09/07 Javascript
JS通过调用微信API实现微信支付功能的方法示例
2017/06/29 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
Vue子组件向父组件通信与父组件调用子组件中的方法
2018/06/22 Javascript
angular2 ng2-file-upload上传示例代码
2018/08/23 Javascript
vue实现设置载入动画和初始化页面动画效果
2019/10/28 Javascript
JS制作简易计算器的实例代码
2020/07/04 Javascript
[01:07:11]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python实现下载pop3邮件保存到本地
2018/06/19 Python
Python使用pickle模块报错EOFError Ran out of input的解决方法
2018/08/16 Python
Python单元和文档测试实例详解
2019/04/11 Python
Python使用itchat模块实现简单的微信控制电脑功能示例
2019/08/26 Python
对Pytorch中Tensor的各种池化操作解析
2020/01/03 Python
python实现PolynomialFeatures多项式的方法
2021/01/06 Python
Snapfish英国:在线照片打印和个性化照片礼品
2017/01/13 全球购物
危爆物品安全大检查大整治工作方案
2014/05/03 职场文书
个人欠款担保书
2014/05/20 职场文书
个人担保书范文
2014/05/20 职场文书
小学教师师德师风自我评价
2015/03/04 职场文书
python周期任务调度工具Schedule使用详解
2021/11/23 Python