regex之如何用 Perl 正则表达式替换字符串中的最后一次出现

cyq1162 阅读:183 2025-06-02 22:19:02 评论:0

好的,这是我的测试(这不是生产代码,只是为了说明我的问题的测试)

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}{$where}i 结尾,它替换了所有出现的 where。

我想用“WHERE users.fake = -1”替换顶级 WHERE(WHERE 的最后一次出现?)(实际上,使用更复杂的模式,但这并不重要)。

有什么想法吗?

请您参考如下方法:

为什么要通过对字符串进行硬编码然后对其进行替换来构建 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'


声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号