C语言实现简化的正则表达式
语法:
- 正则表达式和待匹配字符串都是一行
- “^” 标记正则表达式的开始
- “$” 标记正则表达式的结束
- “*” 匹配前面的子表达式零次或多次
- “+” 匹配前面的子表达式一次或多次
- “?” 匹配前面的子表达式零次或一次, 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,表示该匹配模式是非贪婪的,而不是匹配前面的子表达式
- “{n}” n是一个非负整数。匹配确定的n次
- “{n,}” n是一个非负整数。至少匹配n次
- “{n,m}” m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次
- “.” 匹配除“\n”之外的任何单个字符
- “x|y” 匹配x或y,其中x和y是两个子表达式,如果是字符就是单个字符
- “[xyz]”字符合集,匹配其中的任意一个字符,如果两个字符之间有”-”,就表示这三个字符用于匹配一个ASSIC码值在两字符之间的一个字符,如果开头有”^”,表示负值字符集合。匹配未包含的任意字符
- “(pattern)”一个子表达式,可嵌套
- \b匹配一个单词边界,即是否后面是非标识符字符,只是检测,不匹配实际内容
- \B匹配非单词边界,即是否后面不是非标识符字符,只是检测,不匹配实际内容
- \d 匹配一个数字字符。等价于[0-9]。
- \D 匹配一个非数字字符。等价于[^0-9]。
- \f 匹配一个换页符。等价于\x0c
- \n 匹配一个换行符。等价于\x0a
- \r 匹配一个回车符。等价于\x0d
- \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
- \S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
- \t 匹配一个制表符。等价于\x09
- \v 匹配一个垂直制表符。等价于\x0b
- \w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
- \W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
- \xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.
- \num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两
- 个连续的相同字符。只支持0≤num≤9,并且引用的只能是元表达式,比如(ab)将计数为两个表达式”a”和”b”而忽略括号
策略:
先将正则表达式解析,生成一棵语法树,树枝是”()”“[]”“|”带来的子表达式,节点的exp_id表示这个节点将用于匹配怎样的字符,还有字段记录这个表达式将重复的次数。
“()”的子树是和主树的结构一样的,解析规则也是相同的,但是”[]”和”|”的子树有自己的解析规则
每棵子树的根节点不匹配实际内容,而是用于指示它有子树
再用这棵语法树对字符串进行匹配
Step1:解析语法树
每个函数都只进行一个或特定几个字符的解析,之后递归的调用以递归下降分析
Check:
首先判断是否达到了正则表达式尾
“|”会再当前节点之前插入一个节点,并将当前节点移到插入的节点的孩子上,因为难以只对之后的一个表达式进行特殊处理,所以之后将继续解析。而是在解析完成之后进行再次的处理,遇到”|”的表达式的时候会将其后面的一个表达式放到其孩子树(此时已有一个节点)的后面,这样孩子树将有两个节点
“-”会判断当前的模式,如果在一个中括号中,并且当前节点和后面的都是一个非转义字符,那么就修改当前的节点为字符范围匹配,即便后面的是反斜杠也可以判断是否是非转义字符
“+”“*”会直接修改当前节点的重复次数(即便它有一棵孩子树)
“?”需要判断当前的节点是否已经被限制符修饰过了,如果是就将当前节点设置为非贪婪的,否则就只修改重复次数
在遇到”(““{““[““\”时会进入相应的函数进行特定的解析
递归调用自己进行递归下降解析
Check “\”:
\x将会有一个辅助函数将其后的两个字符解析为十进制整数,并插入为char
\+数字,将会有一个函数寻找对应位置的表达式指针,因为找的只是元表达式,所以不会有孩子节点,而且因为表达式只会被使用而不会被改变,所以引用也可以直接复制,不用深复制
Check”(“:
因为用了全局变量存储表达式树的头节点和当前节点,所以只用备份当前的值,并将值设置为新节点的孩子节点,之后再调用check就可以为新节点的孩子节点生成一个子树
Check”[“:
会和”()”进行相同的操作,差异是调用时指定的模式,而且”[]”再开头会判断是否有”^”
Check”{}”:
识别模式并修改当前的节点重复次数
Step2:检查字符串
Match pattern将会遍历表达式链表,并调用match expression检查每个单独的表达式。子树的遍历将会在match expression中通过调用match pattern进行
源码:
https://github.com/biaoJM/Simple-RegExp-C
C语言实现简化的正则表达式的更多相关文章
- 如何设计一门语言(十)——正则表达式与领域特定语言(DSL)
几个月前就一直有博友关心DSL的问题,于是我想一想,我在gac.codeplex.com里面也创建了一些DSL,于是今天就来说一说这个事情. 创建DSL恐怕是很多人第一次设计一门语言的经历,很少有人一 ...
- go语言之进阶篇正则表达式
正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具.虽然正则表达式比纯粹的文本匹配效率低,但是它却更灵活.按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符 ...
- JavaScript语言精粹 笔记05 正则表达式
正则表达式 正则表达式以方法的形式被用于对字符串中的信息进行查找.替换画图提取操作.可处理正则表达式的方法有:regexp.exec, regexp.test,string.match, string ...
- C#语言之字符串和正则表达式
本文将完成以下两个目标: 一.创建字符串: 二.正则表达式: 首先,我先来介绍一下System.String类: System.String是一个类,专门用于存储字符串,允许对字符串进行许多操作. 使 ...
- 表达式语言之java对正则表达式的处理
正则表达式用于字符串匹配,字符串查找,字符串替换等.例如注册email格式的验证等.java中处理正则表达式相关的类主要有java.lang.String,java.util.regex.Patter ...
- Perl语言学习笔记 9 正则表达式处理文本
1.更换 s/PATTERN/REPLACE/; #返回是否更换成功布尔值 能够使用捕获变量,如:s/(\w)/$1/ 匹配失败则不做不论什么处理 2.定界符 对于没有左右之分的定界符.反复三次就可以 ...
- 正则表达式与领域特定语言(DSL)
如何设计一门语言(十)——正则表达式与领域特定语言(DSL) 几个月前就一直有博友关心DSL的问题,于是我想一想,我在gac.codeplex.com里面也创建了一些DSL,于是今天就来说一说这个事情 ...
- [Java] 简化正则表达式的使用
使用 RegexString.with(string).pattern(pattern).start() + 后续操作(matches,find或者是replace) 源码 package com; ...
- Java语言中的正则表达式
正则表达式是什么? 正则表达式是一种强大而灵活的文本处理工具.初学正则表达式时,其语法是一个难点,但它确实是一种简洁.动态的语言.正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题: ...
随机推荐
- 当一个线程进入一个对象的一个synchronized方法后, 其它线程是否可进入此对象的其它方法?
分几种情况: 1.其他方法前是否加了synchronized关键字,如果没加,则能. 2.如果这个方法内部调用了wait,则可以进入其他synchronized方法. 3.如果其他个方法都加了sync ...
- [caffe]网络各层参数设置
数据层 数据层是模型最底层,提供提供数据输入和数据从Blobs转换成别的格式进行保存输出,通常数据预处理(减去均值,放大缩小,裁剪和镜像等)也在这一层设置参数实现. 参数设置: name: 名称 ty ...
- centos7最小化安装Oracle11gR2
1.准备CentOS 7 系统环境 我以 CentOS-7-x86_64-DVD-1511.iso 为例,简述Oracle 11g的安装过程. 由于是使用静默模式(silent)安装的,无需使用图形化 ...
- .net 参数修饰符
参数修饰符的作用 参数修饰符 作用 无 如果一个参数没有用参数修饰符标记,则认为它将按值传递(pass by value),这意味着被调用的方法收到原始数据的一份副本 out 输出参数由被调用的方法赋 ...
- android startservice无法启动服务
1.android startservice无法启动服务 之前MainActivity.java中启动service源代码如下: private void startMyService() { //启 ...
- debian mysql 定时自己主动备份的脚本
#!/bin/sh LOG=/var/log/mysql-backup.log # mysql db info USER_ROOT=XXXXXX USER_PWD=XXXXXXX # mysql da ...
- cloudstack给已有zone加入物理网络
默认情况下,假设zone建立完后.cloudstack是不提供加入物理网络接口的. 基础架构- 域 - 物理网络 以下仅仅有我们创建zone的时候加入的物理网络 假设想在这个基础上加入一个物理网络是没 ...
- Wing IDE 怎样设置 python版本号
机器上同一时候装了Python3和Python2,使用Wing IDE, 由于Python2和3是有非常大的差别的,所以时不时的须要更改IDE使用的Python版本号.以下介绍方法: 1.打开Edit ...
- Android开发之AudioManager(音频管理器)具体解释
AudioManager简单介绍: AudioManager类提供了訪问音量和振铃器mode控制. 使用Context.getSystemService(Context.AUDIO_SERVICE)来 ...
- 怎样訪问pcie整个4k的配置空间
眼下用于訪问PCIe配置空间寄存器的方法须要追溯到原始的PCI规范. 为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这样的方法能够訪 ...