2017-01-31 11 views
0

可能かどうかわかりませんが、私はwhileループ内のifステートメントから抜け出そうとしています。私はwhileループを終了したくないです。私はexitbreakを使ってみましたが、どちらもwhileループを終了します。whileループ中のif文の中断

問題は、探しているファイルがどのフォルダにあるのかわからないことです。そのため、検索したファイルと一致するときに現在のif文を終了したいのです次のシリアル番号。

シリアル番号のリストを含むdrives-fw-sn.txtというテキストファイルがあります。コードの内訳:

  • Iはwhileループ
  • を用いdrives-fw-sn.txtから一度に1つのシリアル番号で読み出しIファイルの検索は、私は、シリアル番号の最初の発生を印刷find
  • を用いoutput_logと呼ばれます見つかったファイル
  • 次から私は、ログが発見されたことを印刷し、

をしたい。ここが(私のコードの抜粋です3つ以上のテストフォルダです)。 whileループを終了するコマンドは、まだexitコマンドを含んでいます。

while read node; do 
    if find ./test1/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then 
    echo "Log SN $node available" 
    exit 1 
    fi 
    if find ./test2/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then 
    echo "Log SN $node available" 
    exit 1 
    fi 
    if find ./test3/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then 
    echo "Log SN $node available" 
    exit 1 
    fi 
done < drives-fw-sn.txt 
+0

bashでcase文を使ってみましたか? –

+0

@KaranShah私はcase文を使うことを考えましたが、私のアプリケーションには適していないと思われます。 – stevo

+0

'find'の終了ステータスは' -exec'で実行されたコマンドの終了ステータスとは無関係です。 'find'によっていくつのファイルが見つけられますか? 'find'を実行する際に実際のエラーがない限り、終了ステータスは0です。 – chepner

答えて

0

本来、ifから抜け出す方法はありません。しかし、あなたの例の外見からは、exitの代わりにcontinueコマンドを使用して、ループを直ちに反復することができます。

0

continueは、ifステートメントの「抜け出す」方法に関する具体的な質問に対する正解です。 ifのチェックでgrepが成功したかどうかは実際には確認されません。chepnerのコメントを参照してください。

私は最初の場所で問題を回避する方法でこれを行うだろう:

シリアル番号を含むファイルがであることを行っているどのディレクトリかわからないので、それは中関係ありませんあなたはそれらを見ています。代わりに、個別にすべてのディレクトリを一覧表示し、それらのそれぞれにfind -execを実行すると、あなただけの直接すべてのログファイルを試すのgrepを持つことができます。

while read -r node; do 
    cat **/output_log | grep -m 1 "$node" && echo "Log SN $node available" 
done < drives-fw-sn.txt 

これは**/構造を可能にするために、globstarシェル・オプション、shopt -s globstarが必要です。あなたのディレクトリ構造に応じて、あなたはそれを必要とせず、代わりにtest*/*log*/output_logのようなものを使うことができます。

catは、grepが一致するファイルを見つけたら、他のファイルをチェックしないようにするために使用されます。

出力は少し異なります。一致するファイル名の前に付いていますが、対応するgrepオプション(ファイル名を抑制するには-h)で調整できます。

正規表現の照合が必要ないようです。その場合は、固定ストリングにはgrep -Fを使用できます。これは高速にする必要があります。

最後に、シリアル番号がどのように表示されるかに応じて、サブストリングの一致による誤検出を避けるために、-wオプション(完全な単語にのみ一致)を使用することができます。

+0

この質問ではここでは指定しませんでしたが、grepを直接使用することはできません。ディレクトリにファイルが多すぎるためgrepを使用すると帯域幅が多すぎます。まずfindを使ってgrepを使うと、この問題が緩和されます。 – stevo

+0

@stevo「帯域幅があまりにも大きい」とはどういう意味ですか?コマンドラインが長すぎますか? –

+0

帯域幅とは、検索でサーバー上のリソースが過剰に消費され、操作が中断されることを意味します。 findメソッドとgrepメソッドはリソースに課税されることが少なくなります – stevo

1

これは実際にはreturnビルトインを使用すると非常に簡単です。 whileループ内では、小さなファンクションブロック内にifステートメントを設定します。反復中にifの条件が満たされたら、returnを呼び出して、スクリプトがその関数が呼び出された場所に戻り、その時点から続行することができます。私は例を紹介します:

#!/bin/bash 

read -p 'Input: ' HEY 

func() { if true; then return; fi; } 

while true; do 

    echo "Input received!" 
    func && break 

done 

func機能では、あなたがそのようなあなたの複数の条件として、あなたが望む任意の条件値を、保持することができる非常に基本的なif文を持っています。 returnキーワードを含めると、ifステートメントは通訳者の "プログラムカウンタ"を送信します。もしそうなら、func関数が呼び出されたポイントに戻ります。この場合はwhileループ内にあります。したがって、関数が呼び出されていないかのようになり、あなたが見ることができるように、whileループの次のコマンドはbreakキーワードで、whileループを終了します。 if-then-returnコードを含む関数は、ifステートメント内に置かれた条件がインタープリターに最初にロードされている限り、whileループの内側または外側にすることができます(bashは、Cコードが読み込まれる方法)。

遅延メソッドもあり、メイン関数内にスクリプトコード全体をラップするので、ループまたは条件文であっても、スクリプトの任意の時点でreturnを使用できます。ここでは、このように変更し、上記のスクリプトの例です:だけでなく、このようにそれをやって

#!/bin/bash 

MAIN() { 
read -p 'Input: ' HEY 

while true; do 

    if [ "$HEY" == "hello" ]; then 
     return 
    else 
     echo "Incorrect input! Try again!" 
     MAIN 
    fi 

done 
} 

MAIN 

echo "Correct input received!" 

ではなく、グローバル変数を作成するよりも、ローカル変数を保つのを助けます。これを行うには、MAIN関数内のどの時点でも変数をローカルとして定義することができ、MAIN関数が実行されている間に与えられた値だけを保持します。機能が完了すると、変数とその値はもう消えます。

これが役に立ちます。

関連する問題