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 相关文章推荐
js关闭当前页面(窗口)的几种方式总结
Mar 05 Javascript
不使用ajax实现无刷新提交表单
Dec 21 Javascript
分享十五款 jQuery 社交网络分享插件
May 16 Javascript
微信浏览器内置JavaScript对象WeixinJSBridge使用实例
May 25 Javascript
JavaScript中Number对象的toFixed() 方法详解
Sep 02 Javascript
浅析JavaScript中作用域和作用域链
Dec 06 Javascript
vue.js父组件使用外部对象的方法示例
Apr 25 Javascript
微信小程序tabBar底部导航中文注解api详解
Aug 16 Javascript
js+html5生成自动排列对话框实例
Oct 09 Javascript
基于js中this和event 的区别(详解)
Oct 24 Javascript
详解vue如何使用rules对表单字段进行校验
Oct 17 Javascript
JS中箭头函数与this的写法和理解
Jan 14 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
PHP 学习路线与时间表
2010/02/21 PHP
服务器web工具 php环境下
2010/12/29 PHP
php学习笔记 [预定义数组(超全局数组)]
2011/06/09 PHP
Laravel validate error处理,ajax,json示例
2019/10/25 PHP
PHP使用openssl扩展实现加解密方法示例
2020/02/20 PHP
jQuery 操作option的实现代码
2011/03/03 Javascript
JS保留小数点(四舍五入、四舍六入)实现思路及实例
2013/04/25 Javascript
js计算字符串长度包含的中文是utf8格式
2013/10/15 Javascript
Js 正则表达式知识汇总
2014/12/02 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
Angular实现购物车计算示例代码
2017/02/21 Javascript
js实现图片加载淡入淡出效果
2017/04/07 Javascript
Vue组件开发技巧总结
2018/03/04 Javascript
Mint UI实现A-Z字母排序的城市选择列表
2018/12/28 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
2020/08/10 Javascript
Python获取文件ssdeep值的方法
2014/10/05 Python
浅谈django orm 优化
2018/08/18 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
使用python 将图片复制到系统剪贴中
2019/12/13 Python
Pytorch之parameters的使用
2019/12/31 Python
Python使用xlrd实现读取合并单元格
2020/07/09 Python
详解Python yaml模块
2020/09/23 Python
HTML5 Canvas玩转酷炫大波浪进度图效果实例(附demo)
2016/12/14 HTML / CSS
草莓网美国官网:Strawberrynet USA
2016/12/11 全球购物
viagogo波兰票务平台:演唱会、体育比赛、戏剧门票
2018/04/23 全球购物
师范生自荐信
2013/10/27 职场文书
房产继承公证书
2014/04/09 职场文书
财产公证书格式
2014/04/10 职场文书
办公室打字员岗位职责
2014/04/16 职场文书
奉献演讲稿范文
2014/05/21 职场文书
会议室标语
2014/06/21 职场文书
工厂仓管员岗位职责范本
2014/07/17 职场文书
工作会议通知
2015/04/15 职场文书
驾驶员安全责任协议书
2016/03/22 职场文书
vue3中的组件间通信
2021/03/31 Vue.js
vue如何在data中引入图片的正确路径
2022/06/05 Vue.js