带 AND/OR/NOT 的复杂 sed 命令

带 AND/OR/NOT 的复杂 sed 命令

我有一堆php文件,其中有很多select命令。

在每个查询中,我想插入一个列变量admin_id = '$admin_id' ,即如果查询是,则select * from users where abc='xyz' and qwe='fgh'查询应转换为select * from users where admin_id = '$admin_id' and abc='xyz' and qwe='fgh'.

为此,我执行了以下命令sed -i "s/\(\"select.*\)where /\1 where admin_id = '\$admin_id' and /" *.php

where上面的方法已经成功运行,但我仍然面临 SQL 查询的问题,其中查询中没有ie select * from users。我怎样才能插入admin_id = '$admin_id'这些查询?

php 文件中的查询是通过以下方式将查询传递给函数来执行的: execute_query("select * from $table order by username");

格雷普

我可以通过执行以下命令找到仍有待修改的查询:grep 'execute_query' *| grep select| grep -v admin_id > stillleft.txt

答案1

如果你坚持使用sed,你可以使用两个连续的s命令。为了避免在同一行的第一个命令之后运行第二个命令,请t在两者之间添加一个命令;如果前面的s命令进行了替换,这将跳过所有剩余的命令。

sed -e "s/\"select[^\";]* where /&admin_id = '\$admin_id' and /" -e t \
    -e "s/\"select[^\"]*/& where admin_id = '\$admin_id' /" \
    -i  *.php

请注意,这并不健壮:它不能处理select字段选择被分成多行的子句,它不能处理同一行上没有where但例如 a的查询,如果group by查询包含where子字符串等。检查输入和输出以确保您不会遇到任何有问题的情况。

通过 Perl,您可以使用非贪婪重复运算符在第一个保留字或查询末尾停止匹配。这仍然是近似值,但更加稳健。 Perl 还允许替换为构造替换字符串的任意表达式(e替换后带有后缀),因此我们可以在那里放置条件。

perl -i -p -e '
    s[("select.*?)(\b(?:where|group|having|order|limit|procedure|into|for|lock)\b|[;"]|$)]
     [$1 . " where admin_id = '\$admin_id' " . ($2 eq "where" ? "and" : $2)]e
' *.php

PS,这"…'$admin_id'…"看起来像是等待发生的 SQL 注入,除非$admin_id不能包含'(而且我认为格式错误的 UTF-8 也可能有问题)。

答案2

如果您只想添加 afteradmin_id = '$admin_id' andusersafterwhere当它存在时,您可以执行以下操作:

sed "s/\(select.*\)users[ ]*\(where\)\{0,1\}/\1 users where admin_id = '\$admin_id' and /" *.php

-i如果输出符合您的预期,请放置标志。

\(where\)\{0,1\}部分是模拟正则表达式的技巧?,这意味着重复 0 到 1 次,贪婪。

相关内容