
我有一個腳本,它在循環中使用 sed 來刪除列表中包含單字的行:
for i in $list; do
sed -i "/$i/d" file
done
$list
從 SQL 查詢建立:
list=$(psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC")
問題是我的公司最近實施了更嚴格的審計規則,其中包括所有fchown
或fchmod
系統呼叫。使用strace
,我看到每個都sed -i
包含一個fchown
和fchmod
系統呼叫。
對於一個大的列表變量,iowait
系統會急劇上升,而係統實際上會陷入困境,因為auditd正在向其日誌寫入大量的行。
我試圖弄清楚是否有一種方法可以將列表變數在一行中傳遞給 sed ,以便文件僅打開和關閉一次。
我已經問過,對auditd規則的任何改變都是不可能的。
謝謝。
答案1
透過僅運行sed
一次並使用單一sed
腳本,而不是逐一調用無數的內聯命令:
sedscript=$(mktemp)
for i in $list; do
echo "/$i/d" >> "$sedscript"
done
sed -f "$sedscript" -i /path/to/file
rm -f "$sedscript"
答案2
如果您可以仔細分配 中的單詞list
,則可以使用 bash 參數擴充將每個空格替換為正規表示式替代器|
,然後要求grep
為您完成這項工作:
list='auditd the to'
cp file temp &&
grep -Ev "${list// /|}" temp > file &&
rm temp
答案3
如果你的 shell 支援數組,你可以這樣做
mapfile -t arr < <(psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC")
將指令的輸出放入 shell 陣列中,然後
printf '/%s/d\n' "${arr[@]}" | sed -i.bak -f - somefile
將刪除序列套用到somefile
, 適當的位置。如果從psql
命令返回的欄位可能包含sed
.
這與 @DopeGhoti 的解決方案類似,只是它避免了臨時腳本檔案(並且應該處理表格欄位中的空格,如果有必要的話)。
答案4
如果這樣:psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC"
給您一個以空格分隔的單字列表,請嘗試以下操作:
$ psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC" \
| awk -v FS=" " -v OFS="|" '{$1=$1; print "("$0")"}' \
| xargs -I {} sed -i -E '/{}/d' file