手机版

如何构造复杂的正则表达式

时间:2021-10-08 来源:互联网 编辑:宝哥软件园 浏览:

题目本来是《如何构造复杂的正则表达式》,但是感觉有点暧昧的时候就觉得正则表达式很简单,在教人怎么把它变小。相反,我的本意是说,即使是复杂的正则表达式也不怕。找出合适的方法并构建它们。Snopo给出的文本如下:or和name=' zhangshan '和id=001 or age20 or area='% renmin% '等,询问如何提取正确的SQL查询语句。简单分析一下,中间部分还算满意,但是两端有几个像,或者,和。构建能够根据SQL语法解析查询语句的正则表达式应该很复杂。但是,对于具体问题,也可以简单一些。以上格式不良的SQL语句应该是使用程序自动生成的,两端会有一些不符合题意的文字。去掉文字就行了。所以我写了一个正则表达式:s/(?(?or |和|like)\s*) |\s*(吗?(?or |和| like)\ s *)$//mi;这样,多行字符串开头和结尾的所有like、or和可能的空白字符都会被删除,剩下的就是您想要的了。分而治之的答案发出后,Snopo显然对这种“偷懒”的方法不满意。他继续问,能不能写一个正则表达式来匹配符合SQL语法要求的条件查询语句?(只考虑where部分,不必编写完整的select。的确,从快速解决问题的角度来看,只要能有效解决,任何方法都可以用;但是,从学习知识的角度来看,这是一条正确的触底之路,而不是避重就轻。在这种情况下,让我们看看如何使用正则化来解决这个SQL查询语句。最简单的查询语句应该是真假判断,即其中1;真实的地方;真的,在哪里等。这样的语句使用正则表达式,直接/(?-?\ d |真|假)/i .稍微复杂一点的单条语句可以左右比较,也就是复制的代码如下:name喜欢' zhang% ',或者age25,或者work in ('it ',' hr ',' RD ')。为了简化它,结构变成了A OP B.其中a代表变量,OP代表比较运算符,b代表值。A :最简单的a应该是\ w .考虑到实际情况,变量中包含一个点或插入符号,比如table.salary ',可以写成/[\w.`]/。这是一个更一般的细化。如果要求苛刻,也可以让脱字符号同时出现在两边(条件判断)。OP:其中常用的关系是=,=,=,介于,类似,在。使用简单的常规描述,变成:/(?[=]{1,2 } |介于|相似|在)/i .B:b可以分为三种类型:变量、数字、字符串和列表。为了简单起见,这里不考虑算术表达式。变量,一个的定义可以直接扩展。不要重复。数字:使用/\ d/来定义。忘记小数和负数。字符串:包括单引号字符串和双引号字符串。您可以在中间包含转义引号。我写了一个符合这个要求的引号字符串正则表达式,就像:/([''])(?\\['']|[^\\1])*?\1/。然而,由于它只是一个巨大机器的一部分,这样写的风险是极其巨大的。首先,它使用反向引用。其次,反向引用使用全局反向引用号。我写了一个自动生成全局数字的函数来解决这个问题。不过这里谈细节也不算太深。先讲框架,再讲细节。你不应该一开始就陷入细节的海洋。list:list类似于(1,3,4)或(' it ',' hr ',' rd '),由两边带括号的逗号连接的简单变量组成。列表中的单个项目由I表示,I表示数字|字符串。此时,列表变成:/\(我(?我)*?\)/。它的意思是,左括号,一个I,一系列由逗号和I组成的其他列表项(0或更多),以及右括号。为了简单起见,不考虑空白字符。至此,我们可以总结出单个语句的正则框架:S=~ /A OP B/i.s在这里只代表一种说法。更复杂的是多条语句,可以由一条语句组成,中间用和或连接。

合理地构造单条语句,将其稳定地编制为多条语句,任务就完成了。沿用上面的示例,以S代表单条语句,那么复合语句C就是C=~ S(?(?or|and) S)*?/。至此,一个初具规模的条件语句解析器就诞生了。下面以大蟒为例,一步一步实现出来Python。实现重申一句:虽然给出了实现,但是仍请注重思路,忽略代码。复制代码代码如下: #!/usr/bin/python #-*-编码: utf-8-*-# #作者: rex #博客: http://iregex.org #文件名测试。py #创建d : 2010-08-06 17:12 # generage引用字符串;#包括'和字符串#allow和内部索引=0 def gen _ quote _ str():全局索引索引=1 char=chr(96索引)返回r ' '(?Pquote_%s[''])(?\\['']|[^''])*?(?P=quote_%s)'''% (char,char)#简单变量def a(:)返回r '[\ w `] ' #运算符def op():返回r '(?[=]{1,2 } | Between | Like | In)' #列表项In(,#eg: 'a ',23,a.b,' asdfasdf ' aasdf ' def项(): return r '(?%s|%s)' % (a(),gen _ quote _ str())#一个复杂列表,像#eg: (23,24,44),(' regex ',' is ',' good') def items():返回r ' ' \(\ s * % s(?\s* %s)* \s* \)''' % (item(),item())#简单比较#eg: a=15,b23 def s():返回% s \ s * % s \ s *(什么? \ w | % s | % s)' ' ' ' %(a(),op(),gen_quote_str(),items())#复杂比较#名称如张% '和23岁和工作在(' hr ',' it ',' rd ')def(c()):返回r ' '(?ix) %s(?\s*(什么?和|或)\ s * % s \ s *)* %(s(),s())打印A:\t ',a()打印OP:\t ',OP()打印项目:\t ',项目()打印item : \ t ',ITEMS()打印S:\t ',s()打印C:\t ',c()该代码在我的机器上(Ubuntu 10.04,Python 2.6.5)运行的结果是:复制代码代码如下: A: [\w.`] OP:(?[=]{1,2 } |介于|相似|在)项目:(?[\ w `] |(?Pquote_a[''])(?\\['']|[^''])*?(?P=quote_a)) ITEMS: \(\s*(什么?[\ w `] |(?Pquote_b[''])(?\\['']|[^''])*?(?P=quote_b))(?\s*?[\ w `] |(?Pquote_c[''])(?\\['']|[^''])*?(?p=quote _ c)))* \ s * \)s 3360[\ w `]\ s *(什么?[=]{1,2 } |介于|相似|在)\s*(之间?\w |(?Pquote_d[''])(?\\['']|[^''])*?(?P=quote_d) | \(\s*?[\ w `] |(?Pquote_e[''])(?\\['']|[^''])*?(?P=quote_e))(?\s*?[\ w `] |(?Pquote_f[''])(?\\['']|[^''])*?(?P=quote_f)))* \s* \) ) C:(?IX)[\ w `] \ s *(什么?[=]{1,2 } |介于|相似|在)\s*(之间?\w |(?Pquote_g[''])(?\\['']|[^''])*?(?P=quote_g) | \(\s*?[\ w `] |(?Pquote_h[''])(?\\['']|[^''])*?(?P=quote_h))(?\s*?[\ w `] |(?Pquote_i[''])(?\\['']|[^''])*?(?P=quote_i)))* \s* \))(?\s*(什么?和|或)\ s *[\ w `] \ s *(什么?[=]{1,2 } |介于|相似|在)\s*(之间?\w |(?Pquote_j[''])(?\\['']|[^''])*?(?P=quote_j) | \(\s*?[\ w `] |(?Pquote_k[''])(?\\['']|[^''])*?(?P=quote_k))(?\s*?[\ w `] |(?Pquote_l[''])(?\\['']|[^''])*?(?P=quote_l)))* \s* \) ) \s* )*请看匹配效果图

算术表达式我记得刚才说“为了简单起见,这里不考虑算术表达式”。但是解析算术表达式是一个非常有趣的话题,任何算法书都会提到(中缀表达式到前缀表达式等等)。当然也可以用正则表达式来描述。主要思想是复制代码如下: expr-expr term | expr-term | term term-term * factor | term/factor | factor-digit |(expr)和代码:复制代码如下: #!/usr/bin/python #-*-coding : utf-8-*-# # author : rex # blog 3360 http://jb51.net # filename math . py # created : 2010-08-07 00:44 integer=r ' \ d ' factor=r ' % s(?\.“%s”)”%(整数,整数)项='%s(? \s* [*/] \s* %s)* ' %(因子,因子)expr='(?x) %s(?3360 \ s * [-] \ s *% s) *'%(术语,术语)打印expr查看其输出和匹配渲染:

提示:如果不用复杂的正则表达式就能解决问题,那就不要用。如果一定要写复杂的正则表达式,请参考以下原则。从大的方面来看,首先了解待解析文本的整体结构,并将其划分为小部件;我们从细节出发,努力实现每一个小部件,力求让每一个部分都完整牢固,放在大局中也不会冲突。正确组装这些零件。分而治之的好处:当只有一个模块出错,其他部分正确时,可以快速定位错误,消除bug。除非你知道你在做什么,它会有什么副作用,以及是否有可行的解决方案,否则请小心使用捕获括号。对于短正则表达式,多一两个括号是无害的;但是对于复杂的正则表达式,一对额外的括号可能是致命的错误。尝试使用自由空间模式。此时,您可以自由添加注释和空白字符,以提高正则表达式的可读性。

版权声明:如何构造复杂的正则表达式是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。