【转载】递归正则表达式的一般构造方法

标题:递归正则表达式的一般构造方法

作者:xhd2015

原帖:http://tieba.baidu.com/p/4117059926

=======================

先说说问题吧,很老套,如何匹配嵌套的<>

如果你能匹配

class regex<>

恭喜你,最初级的会了,往下看

那么,换成这个

class regex<class<>>

如果你只匹配到红色字符,不幸,你错了

一般表达式对于嵌套的符号对是没有效果的

并不是所有的正则工具都支持递归,实现递归的关键是能对 “规则”引用。

没错,对规则引用(而不是对\1之类的捕获组的反向引用)

如果规则允许嵌套,就意味着允许递归。先看看什么是规则引用,以及和捕获组的反向引用的区别:

表达式 (\s|\w) 意味着 或者\s,或者\w,加上括号以后,就有一个组编号,假设编号为1,那么,

规则引用就是 (?1)

反向引用就是 \1 ←没有括号

区别是,规则引用表示将那个表达式完整地应用在这里,因此(\s|\w)(?1)等价于(\s|\w)(\s|\w)

而捕获组的反向引用就是简单地将匹配到的字符完整地copy到此处

现在进入正题,规则引用怎么构造递归正则?

前面说了规则引用是递归的关键,这句话是什么意思呢?

递归就是自身包含自身,所以,如果规则自身包含自身,那么这就是递归。而很多嵌套的字符串其实也是一种递归。

对于嵌套<>,一般的规则只能匹配有限深度的<>,下面讨论几种情况

匹配1深度 <[^<>]*>

匹配深度2 <[^<>]*<[^<>]*>[^<>]*>

匹配深度3 ……

如果亲自动手写一写1-3的深度,你就会发现规则很简单

我们发现,2是由1递归生成的,因此,我们尝试从2中删除1,用___替代,得到

<[^<>]*___[^<>]*>

这里,特殊性可以代表一般性,所以递归式是

Rn= <[^<>]*Rn-1[^<>]*>

所以,递归表达式就是

(<[^<>]*(?1)*[^<>]*>)

经检验,完全正确

一般性方法:(小菜都会)

1.写出深度1的嵌套表达式

2.写出深度2的嵌套表达式

3.用(?n)替换2中1的位置,就是整个递归表达式。(n是所在组的编号)

这个方法是算法化的,可以由软件实现,即给出符号对,可以生成递归正则

=======================

转载者注,在这个(经我修改的)例子里可以这么写:

[^<>]+<(?0)*>

其中(?0)表示对整个表达式的递归引用

时间: 2024-08-06 05:20:32

【转载】递归正则表达式的一般构造方法的相关文章

【转载】正则表达式学习 &amp; ASCII码表

文章原地址: http://www.jb51.net/tools/zhengze.html <正则表达式30分钟入门教程> 其中有几个地方可以有笔记: \s 匹配任意的空白符 \b 匹配单词的开始或结束 {n} 重复n次 {n,} 重复n次或更多次 {n,m} 重复n到m次 \S 匹配任意不是空白符的字符 [^aeiou] 匹配除了aeiou这几个字母以外的任意字符 捕获(exp) 匹配exp,并捕获文本到自动命名的组里 (?<name>exp) 匹配exp,并捕获文本到名称为na

递归 正则表达式 杨辉三角

递归 1 1 2 3 5 8 13 21 34 ?1 2 3 4 5 6 7 8 9 ? function dg (n){ if (n == 1 || n == 2) { return 1; } else { return dg(n - 1) + dg(n - 2); } } alert(dg(5)); 正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串

[转载]java正则表达式

转载自:http://butter.iteye.com/blog/1189600 1.正则表达式的知识要点1.正则表达式是什么?正则表达式是一种可以用于模式匹配和替换的强有力的工具.2.正则表达式的优点?更少的代码,更高的效率.3.正则表达式如何使用?在下面的教程中我们将学习到正则表达式的用法.4.正则表达式的缺点?需要花一定的时间学习,这个时间由个人决定,一天或者更久一些.2.正则表达式的各种符号及其含义常用的符号 . 表示任意一个字符\s 空格字符(空格键, tab, 换行, 换页, 回车)

【转载】正则表达式

[转载]http://www.runoob.com/regexp/regexp-syntax.html 正则表达式 - 语法 正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串.将匹配的子串替换或者从某个串中取出符合某个条件的子串等. 例如: runoo+b,可以匹配 runoob.runooob.runoooooob 等,+ 号代表前面的字符必须至少出现一次(1次或多次). runoo*b,可以匹配 runob.r

[转载]js正则表达式语法

1. 正则表达式规则 1.1 普通字符 字母.数字.汉字.下划线.以及后边章节中没有特殊定义的标点符号,都是"普通字符".表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符. 举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功:匹配到的内容是:"c":匹配到的位置是:开始于2,结束于3.(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同) 举例2:表达式 "bcd&

[转载]常用正则表达式

常用正则表达式 版本:v0.03 (2013-5-13) 整理:deerchao 说明:正则表达式通常用于两种任务:1.验证,2.搜索/替换.用于验证时,通常需要在前后分别加上^和$,以匹配整个待验证字符串:搜索/替换时是否加上此限定则根据搜索的要求而定,此外,也有可能要在前后加上\b而不是^和$.此表所列的常用正则表达式,除个别外均未在前后加上任何限定,请根据需要,自行处理. 正则表达式(英文:Regular Expression)在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则

Python基础——windows自动化篇(九)-正则表达式

正则表达式(regexp) 正则表达式在某种意义上可以算是字符串操作中的最高级别了,并不是因为它的语法的复杂,而是它的灵活.理解这一点就需要了解正则表达式的本质,无论多么复杂的正则表达式,它的本质就是字符串,目的就是用来记录其他字符串的规律.看似有些抽象,但是其实很容易理解,大多数人在使用dos命令的时候,会使用到通配符,比如在某个目录列出所有的pdf文档,方法就是dir *.pdf——这里的*表示统配,也就是可以代表任何字符串,这个命令也就是列出来所有符合以下命名的文件:任意字符串+”.pdf

Java静态代码块、构造代码块、构造方法的执行顺序

Java静态代码块.构造代码块.构造方法的执行顺序 静态代码优先于非静态的代码,是因为被static修饰的成员都是类成员,会随着JVM加载类的时候加载而执行,而没有被static修饰的成员也被称为实例成员,需要创建对象才会随之加载到堆内存.所以静态的会优先非静态的. 执行构造器(构造方法)的时候,在执行方法体之前存在隐式三步: 1,super语句,可能出现以下三种情况: 1)构造方法体的第一行是this语句,则不会执行隐式三步, 2)构造方法体的第一行是super语句,则调用相应的父类的构造方法

Java——File类,递归

一.File类 获取路径或目录分隔符 public static void main(String[] args) { //File类静态成员变量 //与系统有关的路径分隔符 String separator = File.pathSeparator; System.out.println(separator);// 是一个分号,目录的分割 Linux : //与系统有关的默认名称分隔符 separator = File.separator; System.out.println(separat