bash - 配列の場合、条件が満たされたときに for ループを終了します

okwaves2024-01-25  7

私はスクリプトを作成中です。

スクリプトは複数のサーバー上で実行されます。 TO フィールドに指定されたアドレスに電子メールが送信されます。 スクリプトが実行されているサーバーに応じて、メールの受信者は 2 人 ([email protected] または [email protected]) のいずれかになります。 4 つの事前定義されたサーバーのリストがあります。スクリプトがこれらのサーバーのいずれかで実行されている場合、電子メールは [email protected] に送信されます。それ以外の場合、電子メールは [email protected] に送信されます。

これは正しいと思いましたが、すべてのサーバーで if 条件と else 条件の両方がチェックされるというロジックを見逃していました。

#!/bin/bash
set -x
SERVER_NAME=$(hostname -s)
FILE_TEMP=/tmp/new.log
echo -e "This is a test from SERVER_NAME" >> $FILE_TEMP
subject="sending file from $SERVER_NAME"

Servers=(flipunix1 flipunix2 flipunix3 flipunix7)
for i in ${Servers[*]}
do
    if [ "$SERVER_NAME" == "$i" ];
    then
        to="[email protected]"
        echo -e "server name picked is $SERVER_NAME and i value is $i "
        break
    else
        to="[email protected]"
        echo -e "server name picked is $SERVER_NAME and i value is $i "
        break
    fi
done

also_to="[email protected]"
mail -s "$subject" "$to" "$also_to" < $FILE_TEMP


------------------------

="[email protected]" に送信したいようです。 SERVER_NAME が Servers 配列内の 1 つである場合、そうでない場合は、="[email protected]" に送信します。その場合、ループ ロジックは = "[email protected]" に設定されます。そして、SERVER_NAME が一致しないたびに、たとえ SERVER_NAME が次の反復で一致する可能性がある場合でもループを中断します。この問題は、ブレークを削除することで解決できます。たとえば、

for i in ${Servers[*]}
do
    if [ "$SERVER_NAME" = "$i" ];
    then
        to="[email protected]"
        echo -e "server name picked is $SERVER_NAME and i value is $i "
        break
    else
        to="[email protected]"
    fi
done

ここで=「[email protected]」に進みます。は毎回設定されますが、SERVER_NAME で名前が見つかった場合、ループは to="[email protected]" で終了します。一致するものがない場合にのみ、送信は「[email protected]」のままになります。

単に ="[email protected]" に設定するだけで済みます。ループの前に次のようにします。

#!/bin/bash
set -x
SERVER_NAME=$(hostname -s)
FILE_TEMP=/tmp/new.log
echo -e "This is a test from SERVER_NAME" >> $FILE_TEMP
subject="sending file from $SERVER_NAME"
to="[email protected]"

Servers=(flipunix1 flipunix2 flipunix3 flipunix7)
for i in ${Servers[*]}
do
    if [ "$SERVER_NAME" = "$i" ];
    then
        to="[email protected]"
        echo -e "server name picked is $SERVER_NAME and i value is $i "
        break
    fi
done

also_to="[email protected]"
mail -s "$subject" "$to" "$also_to" < $FILE_TEMP

それ同じことを達成します。 (それが使用されたというメッセージを出力したい場合は、 if ... fi を追加して [ "$to" = "[email protected]"" ] かどうかを確認できます。)

ループを完全に削除し、単純に配列の内容と SERVER_NAME を指定して [[ ... ]] を使用することもできます。例:

#!/bin/bash
set -x
SERVER_NAME=$(hostname -s)
FILE_TEMP=/tmp/new.log
echo -e "This is a test from SERVER_NAME" >> $FILE_TEMP
subject="sending file from $SERVER_NAME"
to="[email protected]"

Servers=(flipunix1 flipunix2 flipunix3 flipunix7)

[[ ${Servers[@]} =~ $SERVER_NAME ]] && {
    to="[email protected]"
    echo -e "server name picked is $SERVER_NAME "
}

also_to="[email protected]"
mail -s "$subject" "$to" "$also_to" < $FILE_TEMP

(選択された内容に基づいて何かを出力したい場合、[ "$to" = "[email protected]" ] ] を確認する場合も同様です)

正しく理解できなかった場合はお知らせください。

(注: [...] 内の文字列の等価性をチェックするための = は 1 つだけです)

3

これはとても素晴らしいロジックですが、見逃していました。驚いたことに、私は数か月前にスクリプトでほぼ同じロジックを使用しました。しかし、ありがとう、あなたはシンプルさを示してくれました。

– アップロードエラー

2020 年 9 月 8 日 22:32

はい、そうします。答えにはまだ疑問が残っていますが、答えが分かり次第、必ず回答済みとしてマークします。

– アップロードエラー

2020 年 9 月 9 日 6:32

わかりました、それでいいです。通常、質問の有効期間は 1 日程度です。編集するとアクティブに戻ります。好きなだけ時間をかけてください。

– デビッド C. ランキン

2020 年 9 月 9 日 7:07



------------------------

これを試してみるとよいでしょう:

#!/bin/bash
set -x
SERVER_NAME=$(hostname -s)
FILE_TEMP=/tmp/new.log
echo -e "This is a test from SERVER_NAME" >> $FILE_TEMP
subject="sending file from $SERVER_NAME"

Servers=(flipunix1 flipunix2 flipunix3 flipunix7)
for i in ${Servers[*]}
do
if [ "$SERVER_NAME" == "$i" ];
then
to="[email protected]"
echo -e "server name picked is $SERVER_NAME and i value is $i "
break
fi
done

if [ -z "$to" ];
then
to="[email protected]"
echo -e "server name picked is $SERVER_NAME "
fi

also_to="[email protected]"
mail -s "$subject" "$to" "$also_to" < $FILE_TEMP

または (短いバージョン)

#!/bin/bash
set -x
SERVER_NAME=$(hostname -s)
FILE_TEMP=/tmp/new.log
echo -e "This is a test from SERVER_NAME" >> $FILE_TEMP
subject="sending file from $SERVER_NAME"

Servers=(flipunix1 flipunix2 flipunix3 flipunix7)

if ! printf "%s\n" "${Servers[@]}" | grep -qw -m 1 "$SERVER_NAME";
then
to="[email protected]"
else
to="[email protected]"
fi

also_to="[email protected]"
mail -s "$subject" "$to" "$also_to" < $FILE_TEMP

6

場合 !printf "%s\n" 「${サーバー[@]}」 | grep -qw -m 1 "$SERVER_NAME";ご返信ありがとうございます。ここのロジックを理解するのを手伝っていただけますか?より深く理解するのに本当に役立ちます。

– アップロードエラー

2020 年 9 月 5 日 5:06

もちろんです!まず、Servers 配列内のすべての要素を個別の行に配置して出力します (printf "%s\n" "${Servers[@]}"); grep コマンドを使用すると、正確 (-w オプション) の最初の一致 (-m 1) によってフィルターされます。) し、stdout への出力を抑制します (-q)。 if ステートメントは、前の行で説明したコマンドを実行し、 if [ $? のように条件を構築するための様式化されたアプローチです。 != 0 ];それから;これは、SC2181 標準で推奨されている構文シェルチェックにすぎません。他にご質問がございましたら、お知らせください。

– Rfroes87

2020 年 9 月 5 日 5:16

-q を指定すると、一致が見つかったときに grep がすぐに終了するため、-m 1 オプションは必要ありません。

– M.ネジャット・アイディン

2020 年 9 月 5 日 5:42

@Rfroes87 説明ありがとうございます。後者の説明は私にとって有益です。そして@Mとして。 Nejat Aydin が提案してくれたので、-m 1 を削除しましたが、違いは見られませんでした。何かお勧めはありますか?

– アップロードエラー

2020 年 9 月 8 日 22:44

@Rfroes87 また、すべてのサーバー名を同じディレクトリ上のファイルに保持したいかどうかも考えています(servers_info.tx など)t) 、以下のようなものと同じ作品を読んでもいいですか?現在エラーが発生しています。もし ! echo -e サーバー情報.txt | grep -qw -m 1 "$SERVER_NAME";次に=「[email protected]」にします。 else to=「[email protected]」"ふぃ

– アップロードエラー

2020 年 9 月 8 日 22:50

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。