从 Vue parseHTML 来学习正则表达式
从 Vue parseHTML 所用正则来学习常用正则语法
Vue parseHTML 中所用的所有正则如下。常见正则规则可参见附录 1,Vue parseHTML 正则所用规则均可在其中找到定义。
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i
const comment = /^<!\--/
const conditionalComment = /^<!\[/
接下来一个个分析上述正则表达式。
attribute
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
分析其结构:
^\s*
匹配 0 至多个以空白字符开头的字符串空白字符的部分捕获组:
([^\s"'<>\/=]+)
匹配并捕获 1 至多次除空白字符
"
'
<
>
/
=
以外的所有字符非捕获组:(?:\s(=)\s(?:"(["]*)"+|'([']*)'+|([^\s"'=<>`]+)))?
\s*
匹配 0 至多个空白字符- 捕获组:
(=)
匹配并捕获=
\s*
匹配 0 至多个空白字符- 非捕获组:
(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>\
]+))`"([^"]*)"+
"
匹配"
([^"]*)
匹配并捕获 0 至多个除"
外的字符"+
匹配 1 至多次"
'([^']*)'+
'
匹配'
([^']*)
匹配并捕获 0至多个除'
外的字符'+
匹配 1 至多次'
- ([^\s"'=<>`]+) 匹配并捕获 1 至多次除
空白字符
"
'
=
<
>
` 外的字符
?
匹配 3 中非捕获组 0 次或 1 次
小结
attribute 表达式匹配的是:
以 0 至多个空白字符开头;
紧接着 1 至多个除
空白字符
"
'
<
>
/
=
以外的字符;紧接着 0 至多个空白字符;
紧接着
=
;紧接着 0 至多个空白字符;
紧接着匹配 0 次或 1 次:
(1)
"
+ 0 至多个除"
外的字符 +"
;(2) 或
'
+ 0 至多个除'
外的字符 +'
;(3) 或 1 至多次除
空白字符
"
'
=
<
>
` 外的字符
例如:
<div id="mydiv" class="myClass" style="color: #ff0000" >
在 Vue 的 parseHTML 时,就能将 id="mydiv"
、class="myClass"
、style="color: #ff0000"
提取出来。
dynamicArgAttribute
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
分析其结构:
^\s*
匹配以 0 至多个空白字符开头捕获组:
((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)
非捕获组:
(?:v-[\w-]+:|@|:|#)
匹配:(1)
v-
+ 1 次或多次包括下划线在内的任意单词字符 +:
(2)或
@
(3)或
:
(4)或
#
\[[^=]+\]
匹配 以[
+ 1 次或多次除=
外的所有字符 +]
[^\s"'<>\/=]*
匹配 0 次或多次除空白字符
、"
、'
、<
、>
、/
、=
以外的字符
- 非捕获组:(?:\s(=)\s(?:"(["]*)"+|'([']*)'+|([^\s"'=<>`]+)))?
已在 attribute
章节分析过。
小结
dynamicArgAttribute 用于匹配:
以 0 至多个空白字符开头
紧接着:
(1)
v-
+ 1 次或多次包括下划线在内的任意单词字符+ :
;(2)或
@
(3)或
:
(4)或
#
紧接着以
[
+ 1 次或多次除=
外的所有字符 +]
匹配 0 次或多次除
空白字符
、"
、'
、<
、>
、/
、=
以外的字符紧接着 0 至多个空白字符;
紧接着
=
;紧接着 0 至多个空白字符;
紧接着匹配 0 次或 1 次:
(1)
"
+ 0 至多个除"
外的字符 +"
;(2) 或
'
+ 0 至多个除'
外的字符 +'
;(3) 或 1 至多次除
空白字符
"
'
=
<
>
` 外的字符
例如:
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
在 Vue 的 parseHTML 时,就能将 v-bind:[attributeName]="url"
这种动态参数提取出来。
ncname
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
首先看 unicodeRegExp
const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/
定义了一系列合法字符,通过 Unicode 字符集范围匹配。
unicodeRegExp.source
用于拿到正则表达式 unicodeRegExp
的字符串。
ncname
即是一系列合法字符的集合。
qnameCapture
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
表示匹配 xxx:xxx
或 xxx
模式的字符。
startTagOpen
const startTagOpen = new RegExp(`^<${qnameCapture}`)
startTagOpen
可匹配标签开始部分,即:<xxx:xxx
或 <xxx
的模式。
<xxx:xxx
代表的是带命名空间的 html 标签,文可参见这里,这种类型的标签主要作用是可以指定标签的命名空间,避免冲突。Vue 对这类的标签也做了解析。
如:<div
或 <math:div
startTagClose
const startTagClose = /^\s*(\/?)>/
^\s*(\/?)>
匹配以 0 至多个空白字符开头,接 0 或 1 个 /
,紧接 >
的字符串。
如: />
endTag
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
匹配以 </
开头,后接合法字符,后接 0 至多个除 >
以外的任何字符,最后接 >
。
如:</div>
doctype
const doctype = /^<!DOCTYPE [^>]+>/i
匹配以 <!DOCTYPE
开头,后接 1 至多次除 >
外的所有字符,后接 >
。注意该匹配模式不区分大小写。
如:<!DOCTYPE html>
comment
const comment = /^<!\--/
匹配以 <!--
开头的字符串。
如:<!--STATUS OK-->
conditionalComment
const conditionalComment = /^<!\[/
匹配以 <![
开头的字符串。条件注释主要用于做浏览器兼容等,文可参见这里
总结
本文以 Vue 源码中 parseHTML 方法为例,分析了其中定义的正则表达式,将常见的正则规则做了梳理,同时可以备查 parseHTML 方法的正则规则,方便后续继续分析该方法。
附录 1 常见正则规则
正则里的特殊字符
* ? + . [ ] ( ) { } | ^ $,共 13 个。
- * 表示匹配前面字符(或括号括起来的表达式,或方括号括起来的字符集)0 次或 多 次;
- (1)? 表示匹配前面字符(或括号括起来的表达式,或方括号括起来的字符集)0 次或 1 次;(2)? 紧跟在其它任何一个限制符(如 * + 等)后时,匹配模式为非贪婪,尽可能少地匹配;
- + 表示匹配前面字符(或括号括起来的表达式,或方括号括起来的字符集)1 次或 多 次;
- . 表示匹配除换行符以外的任意字符 1 次;
- [] 字符集,表示匹配方括号内字符中的其中一个,其中的特殊字符会被当做普通字符处理;
- () 捕获组,表示匹配其中的子表达式;
- {n,m} 匹配前面表达式最少 n 次,最多 m 次
- | 或,常用在捕获组中;
- ^ 匹配字符串的开始位置
- $ 匹配字符串的结束位置
表达式()中常见写法
- (pattern) 匹配 pattern 并获取该匹配;
- (?:pattern) 匹配 pattern 但不获取该匹配;
- pattern1(?=pattern2) 匹配 pattern1 后面跟 pattern2 的字符串,不获取该匹配
- pattern1(?!pattern2) 匹配 pattern1 后面不跟 pattern2 的字符串,不获取该匹配
- (?<=pattern2)pattern1 匹配 pattern1 前面为 pattern2 的字符串,不获取该匹配
- (?<!pattern2)pattern1 匹配 pattern1 前面不为 pattern2 的字符串,不获取该匹配
字符集[]常见写法
- [x|y] 匹配 x 或 y,可为字符串
- [xyz] 匹配 x 或 y 或 z 的字符
- [^xyz] 匹配 非 x 或 y 或 z 的字符
- [a-z] 匹配 a 到 z 的任意小写字符
常见特殊字符
- \b 匹配单词边界
- \d 匹配一个数字字符
- \n 匹配一个换行符
- \r 匹配一个回车符
- \t 匹配制表符
- \s 匹配任何空白字符
- \w 匹配包括下划线的任何单词字符
从 Vue parseHTML 来学习正则表达式的更多相关文章
- vue 和 react 学习 异同点
vue 和 react 学习 异同点 本文不做两个框架比较,只对比了两个框架的语法对比,不代表任何观点,盗版必究,本人唯一qq:421217189 欢迎大家一起来学习探讨,壮我大前端(本文markdo ...
- Vue 超快速学习
Vue 超快速学习 基础知识: 1.vue的生命周期: beforeCreate/created. beforeMount/mounted. beforeUpdate/updated. beforeD ...
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- NodeJS,MongoDB,Vue,VSCode 集成学习
NodeJS,MongoDB,Vue,VSCode 集成学习 开源项目地址:http://www.mangdot.com
- Vue源码学习三 ———— Vue构造函数包装
Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...
- Vue源码学习二 ———— Vue原型对象包装
Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...
- legend2---开发日志12(vue如何进一步学习)
legend2---开发日志12(vue如何进一步学习) 一.总结 一句话总结:还是得找教程(比如视频),自己摸索太浪费时间,也容易踩坑和抓不住重点 还是得找教程(比如视频),自己摸索太浪费时间,也容 ...
- vue.js 初步学习
跟着b站上的视频来学 首先什么是vue.js? 跟着b站上视频来学:(o゚v゚)ノ <!DOCTYPE html> <html lang="en"> < ...
- 4.VUE前端框架学习记录四:Vue组件化编码2
VUE前端框架学习记录四:Vue组件化编码2文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...
随机推荐
- Word·去掉复制粘贴自动添加的空格
阅文时长 | 0.05分钟 字数统计 | 145.6字符 主要内容 | 1.引言&背景 2.声明与参考资料 『Word·去掉复制粘贴自动添加的空格』 编写人 | SCscHero 编写时间 | ...
- 『动善时』JMeter基础 — 23、JMeter中使用“用户自定义变量”实现参数化
目录 1.用户自定义变量介绍 2.使用"用户自定义变量"实现参数化 (1)测试计划内包含的元件 (2)数据文件内容 (3)测试计划界面内容 (4)线程组元件内容 (5)CSV数据文 ...
- [刷题] PTA 7-61 找最长的字符串
程序: 1 #include<stdio.h> 2 #include<string.h> 3 #define N 81 4 5 int main() { 6 char ch[N ...
- 字体:等宽字体与比例字体 - Monospaced font & Proportional font
字体:等宽字体与比例字体 - Monospaced font & Proportional font 量子波儿 2013-08-24 16:54:12 7101 收藏 1分类专栏: 计算机常识 ...
- Canal和Otter讨论二(原理与实践)
上次留下的问题 问题一: 跨公网部署Otter 参考架构图 解析 a. 数据涉及网络传输,S/E/T/L几个阶段会分散在2个或者更多Node节点上,多个Node之间通过zookeeper进行协同工 ...
- Python基础 小白[7天]入门笔记
笔记来源 Day-1 基础知识(注释.输入.输出.循环.数据类型.随机数) #-*- codeing = utf-8 -*- #@Time : 2020/7/11 11:38 #@Author : H ...
- kvm虚拟机管理(3)
一.远程管理kvm虚拟机 (1)上一节我们通过 virt-manager 在本地主机上创建并管理 KVM 虚机.其实 virt-manager 也可以管理其他宿主机上的虚机.只需要简单的将宿主机添加进 ...
- 5.7 echo:显示一行文本
echo命令 能将指定的文本显示在Linux命令行上. -n 不要自动换行 -E 不解析转义字符(默认参数) -e 若字符串中出现以下字符,则需要进行特别处理,而不会将它 ...
- 8.4 parted:磁盘分区工具
parted 对于小于2TB的磁盘可以用fdisk和parted命令进行分区,这种情况一般采用flisk命令,但对于大于2TB的磁盘则只能用parted分区,且需要将磁盘转换为GPT格式. p ...
- 3.21-22 od、tee
3.21 od:按不同进制显示文件 od命令用于输出文件的八进制.十六进制或者其他格式编码的字节,通常用于显示或查看文件中不能直接显示在终端的字符. -A 地址进制 按指定的进制 ...