使用 sed 從列表變數中刪除行

使用 sed 從列表變數中刪除行

我有一個腳本,它在循環中使用 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")

問題是我的公司最近實施了更嚴格的審計規則,其中包括所有fchownfchmod系統呼叫。使用strace,我看到每個都sed -i包含一個fchownfchmod系統呼叫。

對於一個大的列表變量,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

相關內容