帶有 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
。以上已成功執行,但仍然面臨查詢中沒有 SQL 查詢的問題,
where
即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
如果你堅持使用 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的查詢,如果 agroup 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 也可能有問題)。