if thenステートメントとすべてのbashスクリプト

if thenステートメントとすべてのbashスクリプト

複数のファイルで特定の文字列を確認し、見つかった場合は削除する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変数は必要ありません。代わりに、$restartrsyslogrsyslogを一度だけ再起動できます。

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以上ならどうなりますか?grepgrepgrepwc -lgrep-ctmpcheck

これはあなたに効果がありますか?

#!/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

関連情報