
ループ内で 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
syscalls を含む、より厳しい監査ルールを実装したことです。 を使用すると、 every に1 つのおよびsyscall が含まれているstrace
ことがわかります。sed -i
fchown
fchmod
リスト変数が大きい場合、iowait
auditd が膨大な量の行をログに書き込むため、負荷が急上昇し、システムが実際に停止します。
リスト変数を sed に 1 行で渡して、ファイルが 1 回だけ開かれて閉じられるようにする方法があるかどうかを調べています。
すでに質問しましたが、監査ルールを変更することは不可能です。
ありがとう。
答え1
膨大な数のインライン コマンドを 1 つずつ呼び出すのではなく、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
ask にその作業を実行させることができます。
list='auditd the to'
cp file temp &&
grep -Ev "${list// /|}" temp > file &&
rm temp
答え3
シェルが配列をサポートしている場合は、次のようにします。
mapfile -t arr < <(psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC")
コマンドの出力をシェル配列に格納するには、
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