欢迎来到站长教程网!

正则表达式

当前位置:主页 > 网络编程 > 正则表达式 >

应该如何结构巨大的正则表达式

时间:2021-05-05|栏目:正则表达式|点击:

文题原来是《如何结构巨大的正则表达式》,可是以为有些歧义,就感受正则式原来很简朴,我在教人如何将它小事化大一样。正好相反,我的本意是说,纵然巨大的正则式也不怕,找出符合的要领,将其结构出来。

避重就轻

Snopo给出的文本是这样的:or and name='zhangsan' and id=001 or age>20 or area='%renmin%' and like,问,如何提取个中正确的SQL查询语句。

扼要阐明可知,中间部门是合乎要求的,只是两头的有若干个like, or, and。结构可以或许理会合乎SQL语法的查询语句的正则表达式,应该是较量巨大的。但是,对付详细的问题,也可以更简朴。上述的不良构的SQL语句,应该是利用措施自动生成的,它的两头会有一些不切合题意的文本。只要将这些文本去除就可以了。

于是,我写出了正则表达式:s/^(?:(?:or|and|like)\s*)+|\s*(?:(?:or|and|like)\s*)+$//mi;,这样就把多行字串首尾的like, or, and以及大概的空缺字符全部去掉了,剩下的内容即为所求。

分而治之

谜底发已往之后,Snopo显然不是很满足这种“偷懒”的步伐。他继承问道,可否写出正则式,用来匹共同符SQL语法要求的条件查询语句?(只思量where部门即可,不必写完整的select。)

简直,从快速办理问题的角度来说,只要可以或许行之有效地办理,用什么步伐都可以;不外从进修常识的角度来说,不避重就轻,而是刨根问底,才是正途。既如此,就看一下如何利用正则,将该SQL查询语句办理掉。

最简朴的查询语句,应该是真假判定,即 where 1; where True; where false,等等。 这样的语句利用正则式,直接/(?:-?\d+|True|False)/i。

稍巨大些的单条语句,可以是阁下较量,即

复制代码 代码如下:
name like 'zhang%', 或 age>25 ,或 work in ('it', 'hr', 'R&D')

。将其简朴化,布局就变为A OP B。个中A代表变量,OP代表较量操纵符,B代表值。

•A: 最简朴的A,应该是\w+。思量到实际环境,变量包括点号或脱字符,譬喻`table.salary`,可以记为/[\w.`]+/。这是较量笼统的细化。假如要求较量苛刻,还可以做到让脱字符同时在阁下双方呈现(条件判定)。
•OP: Where 常用的几种干系较量为:=, <>, >, <, >=, <=, Between, Like, in。利用简朴的正则描写之,成为:/(?:[<>=]{1,2}|Between|Like|In)/i。
•B: B 的环境又可分为3种:变量,数字,字符串,列表。为简朴起见,这里就不思量算术表达式了。

◦变量的话,直接延用A的界说即可。不赘述。
◦数字:利用/\d+/来界说。不思量小数和负数了。

◦字符串:包罗单引号字串和双引号字串。中间可以包罗被转义的引号。我写了一个切合这一要求的引号字串正则表达式,形如:/(['"])(?:\\['"]|[^\\1])*?\1/。不外,由于它只是复杂呆板的一个零件,这样写的风险是极其大的。首先,它利用了反向引用;其次,该反向引用利用了全局的反向引用编号。我写了自动生玉成局编号的函数,来办理这一问题。不外,这里谈细节是不是太深入了。应该先谈框架,再说细节才对。不该该一入手就陷进细节的汪洋大海。

◦列表:列表是形如(1, 3 , 4) 或 ("it", "hr", "r&d")之类的东东,它由简朴变量以逗号相连,双方加上括号构成。列表的单项以I暗示,它代表 数字|字符串。此时,列表就变为:/\(I(?:,I)*?\)/。它暗示,左括号,一个I,一系列由逗号、I构成的其它列表项(0个或多个),右括号。简朴起见没有思量空缺字符。
•至此,可以总结出单条语句的正则框架:S =~ /A OP B/i。S在此代表单条语句。
更为巨大的是多条语句,可以由单条语句构成,中间利用 and 或 or 毗连。公道地结构单条语句,将其不变地体例为多条语句,任务就完成了。

沿用上面的示例,以S代表单条语句,那么复合语句C就是 C =~ S(?:(?:or|and) S)*?/。至此,一个初具局限的条件语句理会器就降生了。下面以python为例,一步一步实现出来。

Python实现
重申一句:固然给出了实现,可是仍请注重思路,忽略代码。
复制代码 代码如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#author: rex
#blog: http://iregex.org
#filename test.py
#created: 2010-08-06 17:12

#generage quoted string;
#including ' and " string
#allow \' and \" inside
index=0
def gen_quote_str():

global index
index+=1
char=chr(96+index)
return r"""(?P<quote_%s>['"])(?:\\['"]|[^'"])*?(?P=quote_%s)"""% (char, char)


#simple variable
def a():
return r'[\w.`]+'

#operators
def op():
return r'(?:[<>=]{1,2}|Between|Like|In)'


#list item within (,)
#eg: 'a', 23, a.b, "asdfasdf\"aasdf"
def item():
return r"(?:%s|%s)" % (a(), gen_quote_str())


#a complite list, like
#eg: (23, 24, 44), ("regex", "is", "good")
def items():
return r"""\( \s*
%s
(?:,\s* %s)* \s*
\)""" % (item(), item())

#simple comparison
#eg: a=15 , b>23
def s():
return r"""%s \s* %s \s* (?:\w+| %s | %s )""" % (a(), op(), gen_quote_str(), items())

#complex comparison
# name like 'zhang%' and age>23 and work in ("hr", "it", 'r&d')
def c():
return r"""
(?ix) %s
(?:\s*
(?:and|or)\s*
%s \s*
)*
""" % (s(), s())

print "A:\t", a()
print "OP:\t", op()
print "ITEM:\t", item()
print "ITEMS:\t", items()
print "S:\t", s()
print "C:\t", c()

该代码在我的呆板上(Ubuntu 10.04, Python 2.6.5)运行的功效是:
复制代码 代码如下:
A: [\w.`]+
OP: (?:[<>=]{1,2}|Between|Like|In)
ITEM: (?:[\w.`]+|(?P<quote_a>['"])(?:\\['"]|[^'"])*?(?P=quote_a))
ITEMS: \( \s*
(?:[\w.`]+|(?P<quote_b>['"])(?:\\['"]|[^'"])*?(?P=quote_b))
(?:,\s* (?:[\w.`]+|(?P<quote_c>['"])(?:\\['"]|[^'"])*?(?P=quote_c)))* \s*
\)
S: [\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_d>['"])(?:\\['"]|[^'"])*?(?P=quote_d) | \( \s*
(?:[\w.`]+|(?P<quote_e>['"])(?:\\['"]|[^'"])*?(?P=quote_e))
(?:,\s* (?:[\w.`]+|(?P<quote_f>['"])(?:\\['"]|[^'"])*?(?P=quote_f)))* \s*
\) )
C:
(?ix) [\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_g>['"])(?:\\['"]|[^'"])*?(?P=quote_g) | \( \s*
(?:[\w.`]+|(?P<quote_h>['"])(?:\\['"]|[^'"])*?(?P=quote_h))
(?:,\s* (?:[\w.`]+|(?P<quote_i>['"])(?:\\['"]|[^'"])*?(?P=quote_i)))* \s*
\) )
(?:\s*
(?:and|or)\s*
[\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_j>['"])(?:\\['"]|[^'"])*?(?P=quote_j) | \( \s*
(?:[\w.`]+|(?P<quote_k>['"])(?:\\['"]|[^'"])*?(?P=quote_k))
(?:,\s* (?:[\w.`]+|(?P<quote_l>['"])(?:\\['"]|[^'"])*?(?P=quote_l)))* \s*
\) ) \s*
)*

请看匹配结果图:



算术表达式

我记得适才仿佛提到“为简朴起见,这里就不思量算术表达式了”。不外,理会算术表达式是个很是有趣的话题,只要是算法书,城市提及(中缀表达式转前缀表达式,诸如此类)。虽然它也可以利用正则表达式来描写。

其主要思路是:

复制代码 代码如下:
expr -> expr + term | expr - term | term
term -> term * factor | term / factor | factor
factor -> digit | ( expr )

以及代码:
复制代码 代码如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#author: rex
#blog: http://jb51.net
#filename math.py
#created: 2010-08-07 00:44

integer=r"\d+"

factor=r"%s (?:\. %s)?" % (integer, integer)

term= "%s(?: \s* [*/] \s* %s)* " % (factor, factor)

expr= "(?x) %s(?: \s* [+-] \s* %s)* " % (term, term)

print expr

看一下它的输出和匹配结果图:


小贴士

•假如不消巨大的正则式就能办理问题,必然不要用。
•假如必需写较量巨大的正则式,请参考以下原则。
•从大处着眼,先领略待理会的文本的整体布局是什么样子,分别为小部件;
•从细处着手,试图实现每一个小部件,力争每一部门都是完整、健壮的,且放在全局也不会斗嘴。
•公道组装这些部件。
•分而治之的长处:只有某个模块堕落,其它部门没错时,可以迅速定位错误,消除BUG。
•审慎利用捕捉括号,除非你知道本身在做什么,知道它会有什么副浸染,以及是否有可行的办理法子。对付短小的正则式来说,一两个多余的括号是无感冒雅的;可是对付巨大的正则式来说,一对多余的括号大概就是致命的错误。
•只管利用free-space模式。此时你可以自由地添加注释和空缺字符,以便提高正则表达式的可读性。

上一篇:半小时能干正则表达式 经典实例先容

栏    目:正则表达式

下一篇:一串字字符中多个逗号替换为一个 既尺度脱离符(正则表达式)

本文标题:应该如何结构巨大的正则表达式

本文地址:www.jiaocheng88.com.cn/zhengzebiaodashi/62007.html

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:584415406 | 邮箱:584415406#qq.com(#换成@)

Copyright © 2015-2020 小白站长教程网 版权所有 苏ICP备20040415号-3