複数のファイルで特定の文字列を確認し、見つかった場合は削除するbashスクリプトを作成しようとしています。ここに私が持っているものがあり、それがうまくいくと思いますが、部分的にのみ可能です。ファイル内のエントリは削除されますが、2回目に実行すると「Nothing to do...」というメッセージは表示されません。
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck="for f in ${files[*]}; do cat $f | grep blah | wc -l; done"
#for f in ${files[*]}; do cat $f | grep collector.acuity.com | wc -l; done
if [[ "$tmpcheck" != 1 ]];then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi
どんな助けでも大きな助けになります。
答え1
tmpcheck
コードの主な問題(ペア割り当て)は他の回答で指摘されています。変更された/変更されていないファイルの名前を印刷することは必須ではないと仮定するいくつかの異なるアプローチは次のとおりです。
if grep -q -- blah "${files[@]}"
then
sed -i -e '/blah/d' -- "${files[@]}"
systemctl restart rsyslog.service
else
printf '%s\n' 'Nothing to do'
fi
ここで主なアイデアは次のとおりです。
- 必要でない場合は、出力を保存して後でテストするのではなく、複合コマンド内で直接コマンドの(
grep
)終了状態を使用してください。if
- ループからユーティリティを呼び出すことはあまり効率的ではありません。可能な限り、複数のファイルを引数として使用して呼び出すのが最善です。
また、表示されるコードではこれらの問題は発生しませんが、次のことを行います。
- オプションを閉じるタグ(
--
)を追加すると、異常なファイル名を防ぐことができます。 printf
より安全特に拡張結果を印刷する場合はさらにそうですecho
。
答え2
forループ内の言葉にならない内容を確認したいと思います。 tmpcheck変数は必要ありません。代わりに、$restartrsyslog
rsyslogを一度だけ再起動できます。
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
restartrsyslog=
for f in "${files[@]}";do
if grep -q blah "$f"; then
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
restartrsyslog=yes
else
echo -e "Nothing to do, blah has been removed from $f"
fi
done
if [[ -n $restartrsyslog ]] ; then
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
fi
答え3
変数はtmpcheck
そのコマンドの出力ではなくコマンドに設定され、1と等しくないため、式は常にtrueと評価されます。$( ... )
コマンドの出力を置き換えるには、この設定を使用する必要があります。また、ファイルを繰り返す必要はありませんが、そうする場合は、${files[*]}
そのファイルを代わりに使用しないでください${files[@]}
。また、ファイルを読み取ることができるため、単一のファイルcat
にパイプする必要はなく、結果を選択的に計算できるため、パイプに接続する必要もありません。最後に、なぜ1ではないのかを確認したいですか? 2以上ならどうなりますか?grep
grep
grep
wc -l
grep
-c
tmpcheck
これはあなたに効果がありますか?
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck=$(cat "${files[@]}" | grep -c blah)
if (($tmpcheck>=1)); then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi