使用 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

相关内容