2010-10-08 40 views
3

好吧,這裏是我的測試(這不是生產代碼,而只是一個測試來說明我的問題)如何用Perl正則表達式替換字符串中的最後一個匹配項?

my $string = <<EOS; # auto generated query 
       SELECT 
         users.* 
         , roles.label AS role_label 
         , hr_orders.position_label 
         , deps.label AS dep_label 
         , top_deps.label AS top_dep_label 
       FROM 
         users 
         LEFT JOIN $conf->{systables}->{roles} AS roles ON users.id_role = roles.id 
         LEFT JOIN (
           SELECT 
             id_user 
             , MAX(dt) AS max_dt 
           FROM 
             hr_orders 
           WHERE 
             fake = 0 
           AND 
             IFNULL(position_label, ' ') <> ' ' 
           GROUP BY id_user 
         ) last_hr_orders ON last_hr_orders.id_user = users.id 
         LEFT JOIN hr_orders ON hr_orders.id_user = last_hr_orders.id_user AND hr_orders.dt = last_hr_orders.max_dt 
         $join 
       WHERE 
         $filter 
       ORDER BY 
         $order 
       $limit 
EOS 

my $where = "WHERE\nusers.fake = -1 AND "; 

$string =~ s{where}{$where}i; 

print "result: \n$string"; 

代碼,生成查詢,簡單的s結尾{哪裏} {$哪裏}我,它取代了每次發生的地方。

我想用'WHERE users.fake = -1'(實際上,用更復雜的模式,但沒關係)替換頂層的WHERE(最後發生的WHERE?)。

任何想法?

+0

+1良好的正則表達式的問題 - 是否有可能,以及如何找到一個字符串的最後出現。 – 2010-10-08 14:23:56

回答

3

爲什麼你想通過硬編碼字符串來建立你的sql查詢,然後對它們進行替換?不會像

my $proto_query = <<'EOQ' 
select ... where %s ... 
EOQ 

my $query = sprintf $proto_query, 'users.fake = -1 AND ...'; 

或(最好的,因爲它避免了大量的問題,你的初步做法和上面有)使用一個模塊,如Data::Phrasebook::SQL讓很多事情變得更簡單?

如果你真的想要去的替換工作,你可能會尋找類似

my $foo = "foo bar where baz where moo"; 
$foo =~ s/(.*)where/$1where affe and/; 
say $foo; # "foo bar where baz where affe and moo" 

即取儘可能多的,你可以到你不能繼續拍攝任何沒有沒有一個「在哪裏」立即跟隨你所捕獲的東西,然後插入你捕獲的任何東西,再加上你想做的任何修改。

但是,請注意,如果您使用它來破壞SQL查詢,這會有各種限制。要做正確的事情,你必須在某種程度上真正理解SQL。考慮一下,例如,select ... where user.name = 'where'

+0

所有這些東西出現在orm-like查詢構建引擎中,這是測試顯示此引擎中的錯誤。目前,我無法承受從零開始重寫甚至部分文件 – jonny 2010-10-08 07:59:43

+0

我知道「貪婪」的方式,顯然它不適用於沒有s標誌的多行字符串。這個正則表達式更簡單,謝謝! – jonny 2010-10-08 08:24:26

2

顯然,我需要的是Look-ahead正則表達式功能

我正則表達式是

s{where(?!.*where)}{$where}is; 
2

解析SQL查詢正確的方法是使用一個分析器,而不是使用正則表達式做的事。

看到SQL::Statement::Structure - 分析和檢查結構的SQL查詢

+0

downvote的任何理由? – 2010-10-08 14:57:10

相關問題