bashでif文を繰り返す方法は?

bashでif文を繰り返す方法は?

ユーザーに質問し、答えを提供し、iという変数に保存するようにし、答え(ファイル)が存在し、書き込み可能な場合はそれを読み、内容を把握します。ファイルと挿入このコンテンツは新しいコンテンツに書き込まれます。ファイルが存在しない場合、またはユーザーがファイルに対する十分な権限を持っていない場合は、警告メッセージが表示され、プログラムは3秒間スリープモードに入り、ループを再開します。なぜ動作しないのですか?警告は消えず、サイクルは続行されません。

echo "$(tput setaf 4)  Tell me where the file is:"
printf "\n"

a=false
while [ $a=true ]; do
    read i
    if [ -w $i ]
        then cat $i | grep stuff > i2
    else
        a=true
        printf "Oh something is wrong, try again!"
            sleep 3
    fi
done

答え1

文法的、論理的なエラーがあります。

これは$a=true比較操作ではなく単純な文字列です。簡単に比較できるようにスペースで区切ります。"$a" = true

これを完了したら、あらかじめ設定しておいたので、ループにまったく入らなくなりますa=false

ループに陥ると、それ以外のものにa設定されたことがなく、true他のシャットダウンメカニズムが提供されないため(たとえばbreak)シャットダウンできません。

答え2

他の人が指摘したように、コードには論理エラーと構文エラーがあります。これシェルチェックのウェブサイト文法エラーを解決するのに役立ちます。

ここに私の意見があります。 2つのバージョンのコードがあります。 (私が好む)最初のものはユーザー対話を持っていませんが、コマンドラインでパス名を使用します。 2番目は対話的にパス名を求めます。

対話的にパス名の入力を求められない最初の理由は、スクリプトユーザーがコマンドラインまたはスクリプトプロンプトでパス名を書き込んだ場合は違いがなく、パス名にスクリプトプロンプトを使用すると違いがないためです。たとえば、クローン操作や端末が接続されていない他の場所で使用できます。

#!/bin/sh

pathname=$1

if ! grep 'pattern' <$pathname >i2; then
    echo 'Something is wrong' >&2
fi

上記の文は、echo次の場合に実行されます。

  • $pathnameのファイルを読み込めない
  • ファイルi2に書き込めない
  • パターンが見つかりません$pathname(あなたのコードとは異なりますが、以下を参照してください)

一般的な診断メッセージをカスタマイズするのと同様に、エラーメッセージは標準エラーに記録されます。

インタラクティブなプロンプトと遅延:

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    if grep 'pattern' <$pathname >i2; then
       break
    fi

    echo 'Something is wrong' >&2
    sleep 3
done

grepこれには、ユーザーからデータを読み取り、呼び出しが正常な場合にループから出る無限ループがあります。何らかの理由で(上記の3つの理由のいずれか)失敗すると、パス名の入力をgrep求められます。


どちらのコードも読み取り可能なファイルに対して別々のテストを持っています(grep何も見つからないか、出力ファイルに書き込めないため失敗する可能性があります)。

まず、非対話型バージョン:

#!/bin/sh

pathname=$1

if [ ! -r "$pathname" ]; then
    echo 'Something is wrong' >&2
fi

grep 'pattern' <$pathname >i2

そしてインタラクティブなバージョンがあります。

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    if [ -r "$pathname" ]; then
       grep 'pattern' <$pathname >i2
       break
    fi

    echo 'Something is wrong' >&2
    sleep 3
done

または、ループがユーザー入力と検証のみを処理する対話型バージョン:

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    [ -r "$pathname" ] && break

    echo 'Something is wrong' >&2
    sleep 3
done

grep 'pattern' <$pathname >i2

答え3

次のように、単純な中断を使用して無限ループを停止してみてください。

echo "$(tput setaf 4)  Tell me where the file is:"
echo # This prints empty line like printf "\n"

while true; do # 'while true' or 'while :' is infinite loop
    read i
    if [ -r $i ]    # You probably mean -r (readable) and not -w (writable)
    then
        cat $i | grep stuff > i2
        break # 'break' ends loop
    else
        echo -n "Oh something is wrong, try again!" # 'echo -n' means print without newline character
        sleep 3
    fi
done

修正に関するコメントと説明があります。

関連情報