尋找sql的正規表示法,想破頭想不出怎麼比對

edited 十月 2013 in 進階PHP討論
我想找出一個文件內的任何sql語法並把他讀進變數內
例如我想找以下文件的create table,insert into的sql

<?/*
:::setdata=關於本站
:::setdata=intro,
:::setdata=INSERT INTO `limittable` (`afname` , `filename` , `limitlv` ) VALUES ('af/intro','photo.php', '0'),('af/intro','intro.php', '0'),('af/intro','edit.php', '0')
:::setdata=CREATE TABLE `intro` (
`dateid` VARCHAR( 15 ) NOT NULL ,
`name` VARCHAR( 20 ) NOT NULL ,
`htmldata` TEXT NOT NULL ,
`readlv` INT( 3 ) NOT NULL
);
:::setdata=INSERT INTO `intro` VALUES ('20060531153425', 'socket0.5', '
socket', 0);
:::setdata=
*/?>

這是我的做法,我想先找create table 的sql,並放入$info,但一直沒成功
$data = file_get_contents("info.php");
eregi('(CREATE TABLE .+ \(.+\);)',$data,$createinfo);
最難搞的是最後,因為都會找到別的資料
接著是找出insert into,但因為有2個insert into 的sql而且又在不同地方
目前還沒想到要怎麼去找
想請正規表示法強的人可以提示我一下
(ps,create table的sql是要適用各種建立表格的sql)

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=2408

評論

  • edited 二月 2007
    對了,文件也會是不同資料,sql也會是不同的,唯一相同的,就只有create table 和insert into ,因為是要做sql語法搜尋用的
  • edited 二月 2007
    REGEX 基本上是不跨行的,換行字元也是一個 quantity...
    So, 為了避免困擾,要先把換行字元消掉。

    $crlfTrSpace = array(
    "\n" => ' ',
    "\r" => ' '
    );

    $data = strtr(file_get_contents("info.php"), $crlfToSpace);


    eregi('(CREATE TABLE .+ \(.+\);)',$data,$createinfo);

    在 SQL 語法,一行指令結束於一個分號 (;) ,所以我們要找到的是指令關鍵字以後的第一個分號為止的內容。但你的 REGEX 忘了抑止貪婪比對。基於貪婪比對的原則, REGEX 會一直找到「最後一個」分號 ( ; ),而不是指令關鍵字後第一個分號。所以不是用 .+ ,而要改成 [^;]+

    preg_match_all('/CREATE TABLE\s+\([^;]+\)/i', $data, $m);

    ps. PCRE 比 POSIX REGEX 快,所以改用 preg_match_all
  • edited 二月 2007
    基於貪婪比對的原則, REGEX 會一直找到「最後一個」分號 ( ; )
    這句話真是一語驚醒夢中人
    我把原本改成(create table[^;]+;)即可了
    不過我沒用preg_match_all,因為會出現錯誤訊息
    所以使用eregi來做

    但至少解決了大部份的sql
    太感謝了
  • edited 二月 2007
    preg 會 ereg 的 REGEX 寫法有些不同, preg 的前後一定要加 / ,沒有加的話一定會錯誤;但 ereg 就不可以加。一個 REGEX 用 ereg 和 preg 的寫法比較如下:
    eregi( '[a-z]+', $s );
    preg_match( '/[a-z]+/i', $s );


    分號在 sql 指令中有特殊意義(就是指令結束)。在sql中,只有被單引號括起來的分號會被視為字串的一部份。但在你的需求中,是從 php code 中抓出 sql 指令,通常在此情形下的 sql 指令的字串部份都是用變數,例如:
    "insert into $table (poster, comment) values ('$userName', '$postComment');"

    我想不用擔心碰到有分號的情形。
Sign In or Register to comment.