一条匹配SQL语句的正则

原文

先说明一下啦,这篇文章花了我近一个小时才完成的,都是一个字一个字地敲出来的,中间也做了很多测试,所以我希望看过的朋友都回一下贴当是对我精神上的鼓励啦。。。。

今天在CSDN上看到了一个问题,如何用PERL中的正则匹配一条输入的SQL语句的正确性,感觉很有用。语句乍一看很恐怖,慢慢分析下来就慢慢明白了,正则好强大。

见例子:
$sql = ” select * from tableName where type=type1 oder by id DESC”;
现在主要是匹配$SQL语句的正确性,首先select from   tableName必须有,WHERE语句和ORDER语句可选。
用PERL的正则这么写:
if( $sql =~ /^\s*select\s+(\*|[\w_]+(\s*,\s*[\w_]+)*)\s+from\s+[\w_]+(\s+where\s+[\w_]+\s*=\s*\S+)?(\s+order\s+by\s+[\w_]+ (\s+(ASC|DESC))?)?\s*$/i){
print “sql match!”;
}else{
print “sql error!”;
}

这段代码第一次看见肯定被吓得半死,不过慢慢研究还是挺有意思的。。。现在我来一步一步讲解吧。
首先讲解之后先来熟悉一下正则的几个基本知识。
/   /   放在里面的匹配模式,最后的一个i表示不区分大小写。
\s表示空格 *表示匹配0个或多个,+表示匹配1个或多个,这个匹配模式里面有很多\s*   \s+之类的,主要是因为要匹配空格,像 select * from中间的空格是必须有的就要用\s+, 而像开头,最后的空格是可有可无的就用\s*.
\w表示字母或数字,   \S表示匹配非空格字符.
| 表示匹配两者中的一个.     [] 表示匹配里面的内容。
^表示匹配开头, $表示匹配末尾。。
好啦,差不多啦,可以开始讲了。
首先看到的是 $sql =~ 后面的那个 =~是PERL特有的,叫约束符。PERL默认的是从<STDIN>标准输入里面获取内容, 而=~告诉解释器所需要的内容从左边的变量即$sql里面获取,不会太难理解吧。
然后开始进入匹配状态,^ 感觉可有可无,试验过了没有也行,\s*表示select前面可以有空格也可以没有,接着匹配select,然后是一个\s+,因为select后面的空 格是必须有的,所以用+,再往后就比较复杂,先把这部分当成一个整体(\*|[\w_]+(\s*,\s*[\w_]+)*),先讲理论知 识,select后面可以是 * 表示任何东西,也可以是一项 id,或多项 id,name等。现在明白有三种选择吧,\* 表示 * ,*在正则里面是元字符,表示匹配0个或多个,要用* 就要用转义字符\,后面跟着 | 表示或的意思,意思是可以是匹配前者也可以匹配后者,前者是 * ,后者呢,后者是。。往下看,先来一个[\w_]+,这个表示可以匹配字母,数字和_,可以匹配一个或多个,像可以匹配id,ID,id_test之类 的。后面再来一串(\s*,\s*[\w_]+)* ,刚才说了select后面可以跟*,也可以跟一项,也可以跟多项,这一串就是用来匹配多项的,如select id,name,sex from ******,这条语句,两个\s*表示在逗号前后可以有空格也可以无,后面又是匹配一个字段的,可以匹配数字,字母和_。最后的*表示这部分可以是0个 或多个,比如你只选取一个ID的时候后面就不需要了,不知道这样说大家看得明不明白。
好了,解决了不少,不知道你们感觉怎么样了,完全不知所云还是有点感觉了,呵呵,不懂再提出问题吧。
再往下看,\s+from\s+[\w_]+ ,正则匹配还是要一块一块解决才比较好理解。\s+表示要匹配一个或多个空格,这个刚才解释过了吧。后面匹配from,再往后又是一个\s+,不用解释了 吧,后面跟[\w_]+表示要匹配一个tableName,表可以由数字,字母和_组成,OK。。。搞定一段,再往下。。。(\s+where\s+ [\w_]+\s*=\s*\S+)?这段要匹配where语句,where语句是可有可无的,但有的话也只能出现一次,所以用()?把整个where语 句括起来,?表示可以出现0次或1次,\s+跳过。。。接着一个where,后面又一个\s+,PASS跳,别跟我说还需要解释\s+这个 啊,^_^。。。。后面一个[\w_]+匹配一个字段,\s*表示=号前面空格可有可无,=后面一个\s*作用也一样,接着是一个\S,这是大写的S,表 示匹配非空格,好像跟[\w_]+作用差不多,不过数据库表里面的字段好像只能用数字,字母和_起名字的,那把这个\S+改为 [\w_]+ 就行了。。。好了,来解决最后一部分了,(\s+order\s+by\s+[\w_]+ (\s+(ASC|DESC))?)?这一串是用来匹配order by的,跟where语句一样也是可有可无的,所以都用()?括起来跟个?号。。。。\s+order\s+by\s+[\w_]+这一串应该不用解释 吧,就是匹配order by的,前面要有空格,说说后面(\s+(ASC|DESC))?这个,order by如果不注明是ASC升序还是DESC降序默认是降序的,所以ASC|DESC是可有可无的,用?匹配。。。。。差不多了吧,最后一个\s*就是匹配空 格的。。。。。啊。。。终于讲完,这是我花了近一个小时才写完的啊,中间也测试过了都没问题,虽然要匹配复杂的SQL语句不行,不过一般的SQL语句都是 这样,所以能搞定大部分的SQL语句啦,正则表达式是个很强大的工具,但又是难掌握的,刚开始接触的时候我完成是梦游。。。。不过只要坚持慢慢体会,你就 会知道正则是有多么的强大了。。。好了,该歇会了。。。眼睛都花了。。。

相关日志

楼被抢了 2 层了... 抢座Rss 2.0或者 Trackback

发表评论