ES6第六章正则的扩展

本文介绍ES6中正则表达式的增强功能,包括构造函数改进、Unicode字符识别、预定义模式、修饰符作用及新引入的后行断言、Unicode属性类和具名组匹配等。

ES6第六章

  • EegExp构造函数

    第一种情况是: 参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。
    var regex = new RegExp('xyz', 'i'); // 等价于 var regex = /xyz/i;
    第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。在ES5中当第一个参数是正则表达式时,不支持第二个参数
    如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且会忽略原有的正则表达式的修饰符,只使用新指定的修饰符。

  • 字符串的正则方法

    match()、replace()、search()和split()ES6 将这 4 个方法,在语言内部全部调用RegExp的实例方法

  • u 修饰符

    对于码点\uFFFF的字符用u后缀才能正确识别。例如: /^\uD83D/u.test(’\uD83D\uDC2A’) // false
    /^\uD83D/.test(’\uD83D\uDC2A’) // true`

    • Unicode 字符表示法
      正则表达式中必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词。
      	/\u{61}/.test('a') // false  
      	/\u{61}/u.test('a') // true
      
    • 预定义模式
      u修饰符也影响到预定义模式,能否正确识别码点大于0xFFFF的 Unicode 字符。
      /^\S$/.test('𠮷') // false
      /^\S$/u.test('𠮷') // true
      
    • i 修饰符
      i 修饰符用于执行对大小写不敏感的匹配
      /[a-z]/i.test('\u212A') // false
      /[a-z]/iu.test('\u212A') // true
      
    • 转义
      没有u修饰符的情况下,正则中没有定义的转义(如逗号的转义,)无效,而在u模式会报错。
      	/\,/        // /\,/
      	/\,/u       // 报错
      
  • RegExp.prototype.unicode属性
    正则实例对象新增unicode属性,表示是否设置了u修饰符
  • y 修饰符
    • y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始。
      var s = 'aaa_aa_a';
      var r1 = /a+/g;
      var r2 = /a+/y;
      r1.exec(s) // ["aaa"]		剩余字符串 ”_aa_a“
      r2.exec(s) // ["aaa"]       剩余字符串 ”_aa_a“
      r1.exec(s) // ["aa"]		剩余字符串中全局匹配
      r2.exec(s) // null			从第一个字符开赛开始匹配
      
      事实上,y修饰符号隐含了头部匹配的标志^。
      	const TOKEN_Y = /\s*(\+|[0-9]+)\s*/y;
      	const TOKEN_G  = /\s*(\+|[0-9]+)\s*/g;
      	tokenize(TOKEN_Y, '3x + 4')
      	// [ '3' ]		
      	tokenize(TOKEN_G, '3x + 4')				
      	// [ '3', '+', '4' ]		g修饰符会忽略非法字符
      	function tokenize(TOKEN_REGEX, str) {
      		  let result = [];
      		  let match;
      		  while (match = TOKEN_REGEX.exec(str)) {
      		    result.push(match[1]);
      		  }
      		  return result;
      		}
      
  • RegExp.prototype.sticky 属性
    表示是否设置了y修饰
    var r = /hello\d/y;
    r.sticky // true
    
  • RegExp.prototype.flags 属性
    返回正则表达式的修饰符
    	/abc/ig.source
    	// "abc"		ES5
    	/abc/ig.flags
    	// 'gi'       ES6
    
  • s 修饰符:dotAll 模式

    (.)是一个特殊字符,可以代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符(该字符表示一行的终结)U+000A 换行符(\n),U+000D 回车符(\r),U+2028 行分隔符(line separator),U+2029 段分隔符(paragraph separator)

    	/foo.bar/.test('foo\nbar')
    	// false
    	/foo[^]bar/.test('foo\nbar')
    	// true
    	/foo.bar/s.test('foo\nbar')
        // true
    
    dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。
    	const re = /foo.bar/s;
    	// 另一种写法
    	// const re = new RegExp('foo.bar', 's');
    	re.test('foo\nbar') // true
    	re.dotAll // true
    	re.flags // 's'
    
  • 后行断言
    • JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)已经支持。

    • “先行断言”指的是,x只有在y前面才匹配,必须写成/x(?=y)/
    • “先行否定断言”指的是,x只有不在y前面才匹配,必须写成/x(?!y)/。
    	/\d+(?=%)/.exec('100% of US presidents have been male')  // ["100"]
    	/\d+(?!%)/.exec('that’s all 44 of them')                 // ["44"]
    
    • “后行断言”正好与“先行断言”相反,x只有在y后面才匹配,必须写成/(?<=y)x/
    • “后行否定断言”则与“先行否定断言”相反,x只有不在y后面才匹配,必须写成/(?<!y)x/。
      /(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"]
      /(?<!\$)\d+/.exec('it’s is worth about €90')       // ["90"]
      
      “后行断言”的实现,需要先匹配/(?<=y)x/的x,然后再回到左边,匹配y的部分。这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。
      /(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"]
      /^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]
      
      “后行断言”的反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。
      /(?<=(o)d\1)r/.exec('hodor')  // null
      /(?<=\1d(o))r/.exec('hodor')  // ["r", "o"] 反斜杠引用(\1)必须放在()前面才可以
      
  • Unicode 属性类

    ES2018 引入了一种新的类的写法\p{…}和\P{…},允许正则表达式匹配符合 Unicode 某种属性的所有字符。

    \p{UnicodePropertyName=UnicodePropertyValue}	//Unicode 属性类要指定属性名和属性值。
    
    const regexGreekSymbol = /\p{Script=Greek}/u;		//匹配一个希腊字母
    regexGreekSymbol.test('π') // true
    
    \P{…}是\p{…}的反向匹配,即匹配不满足条件的字符。
    
    // 匹配所有数字
    const regex = /^\p{Number}+$/u;
    regex.test('²³¹¼½¾') // true
    regex.test('㉛㉜㉝') // true
    regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true
    
    // 匹配所有空格
    \p{White_Space}
    
    
    // 匹配 Emoji
    /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu
    
  • 具名组匹配
    • ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。
      const RE_DATE = /(?\d{4})-(?\d{2})-(?\d{2})/;

      const matchObj = RE_DATE.exec('1999-12-31');
      const year = matchObj.groups.year; // 1999
      const month = matchObj.groups.month; // 12
      const day = matchObj.groups.day; // 31
      
  • 解构赋值和替换
    • 可以使用解构赋值直接从匹配结果上为变量赋值
      let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
      one  // foo
      two  // bar
      
  • 引用
    • 如果要在正则表达式内部引用某个“具名组匹配”,可以使用\k<组名>的写法。
      const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
      RE_TWICE.test('abc!abc') // true
      RE_TWICE.test('abc!ab') // false
      
  • 正则匹配索引
    • 由于正则匹配结果的开始位置和结束位置,目前获取并不是很方便。正则实例的exec()方法,返回结果有一个index属性,可以获取整个匹配结果的开始位置,但是如果包含组匹配,每个组匹配的开始位置,很难拿到。
      第三阶段提案,为exec()方法的返回结果加上indices属性,在这个属性上面可以拿到匹配的开始位置和结束位置。

    	const text = 'zabbcdef';
    	const re = /ab/;
    	const result = re.exec(text);
    	result.index // 1
    	result.indices // [ [1, 3] ]
    
    如果正则表达式包含组匹配,那么indices属性对应的数组就会包含多个成员,提供每个组匹配的开始位置和结束位置。
    	const text = 'zabbcdef';
    	const re = /ab+(cd)/;
    	const result = re.exec(text);
    	result.indices // [ [ 1, 6 ], [ 4, 6 ] ]
    
    如果正则表达式包含具名组匹配,indices属性数组还会有一个groups属性。该属性是一个对象,可以从该对象获取具名组匹配的开始位置和结束位置。
       const text = 'zabbcdef';
       const re = /ab+(?<Z>cd)/;
       const result = re.exec(text);
       result.indices.groups // { Z: [ 4, 6 ] }
    
    如果获取组匹配不成功,indices属性数组的对应成员则为undefined,indices.groups属性对象的对应成员也是undefined。
    	const text = 'zabbcdef';
    	const re = /ab+(?<Z>ce)?/;
    	const result = re.exec(text);
    	result.indices[1] // undefined
    	result.indices.groups['Z'] // undefined
    
  • String.prototype.matchAll()
    • String.prototype.matchAll()方法,可以一次性取出所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。
    const string = 'test1test2test3';
    const regex = /t(e)(st(\d?))/g;
    
    for (const match of string.matchAll(regex)) {
      console.log(match);
    }
    // ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
    // ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
    // ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
    
本项目构建于RASA开源架构之上,旨在实现一个具备多模态交互能力的智能对话系统。该系统的核心模块涵盖自然语言理解、语音转文本处理以及动态对话流程控制三个主要方面。 在自然语言理解层面,研究重点集中于增强连续对话中的用户目标判定效能,并运用深度神经网络技术提升关键信息提取的精确度。目标判定旨在解析用户话语背后的真实需求,从而生成恰当的反馈;信息提取则专注于从语音输入中析出具有特定意义的要素,例如个体名称、空间位置或时间节点等具体参数。深度神经网络的应用显著优化了这些功能的实现效果,相比经典算法,其能够解析更为复杂的语言结构,展现出更优的识别精度与更强的适应性。通过分层特征学习机制,这类模型可深入捕捉语言数据中隐含的语义关联。 语音转文本处理模块承担将音频信号转化为结构化文本的关键任务。该技术的持续演进大幅提高了人机语音交互的自然度与流畅性,使语音界面日益成为高效便捷的沟通渠道。 动态对话流程控制系统负责维持交互过程的连贯性与逻辑性,包括话轮转换、上下文关联维护以及基于情境的决策生成。该系统需具备处理各类非常规输入的能力,例如用户使用非规范表达或对系统指引产生歧义的情况。 本系统适用于多种实际应用场景,如客户服务支持、个性化事务协助及智能教学辅导等。通过准确识别用户需求并提供对应信息或操作响应,系统能够创造连贯顺畅的交互体验。借助深度学习的自适应特性,系统还可持续优化语言模式理解能力,逐步完善对新兴表达方式与用户偏好的适应机制。 在技术实施方面,RASA框架为系统开发提供了基础支撑。该框架专为构建对话式人工智能应用而设计,支持多语言环境并拥有活跃的技术社区。利用其内置工具集,开发者可高效实现复杂的对话逻辑设计与部署流程。 配套资料可能包含补充学习文档、实例分析报告或实践指导手册,有助于使用者深入掌握系统原理与应用方法。技术文档则详细说明了系统的安装步骤、参数配置及操作流程,确保用户能够顺利完成系统集成工作。项目主体代码及说明文件均存放于指定目录中,构成完整的解决方案体系。 总体而言,本项目整合了自然语言理解、语音信号处理与深度学习技术,致力于打造能够进行复杂对话管理、精准需求解析与高效信息提取的智能语音交互平台。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值