私のスクリプトが複数の関数を呼び出すのはなぜですか? [コピー]

私のスクリプトが複数の関数を呼び出すのはなぜですか? [コピー]

私はLinuxを非常に簡単に設定できるようにいくつかのスクリプトセットを作成しました。だから私はこのスクリプトを別の関数にし、すべて1つのスクリプトに入れました。ユーザーが数値のいずれかを入力すると、関数が呼び出されるように数値を設定しました。ただし、ユーザーが数値を入力すると、スクリプトはすべての関数を呼び出します。

n=1
#note you need spaces between [ ]
while [ $n == 1 ]
do
    echo "Base install=1"
    echo "Mintrepos=2"
    echo "Asusn13 driver=3"
    echo "Install Standard openbox=4"
    echo "Install Xfceopenbox=5"
    echo "backing up standard open box config=6"
    echo "backing up openboxfce=7"
    echo
    read choice
    if [ "$choice"==1 ]
    then
        baseinstall
    fi
    if [ "$choice"==2 ]
    then
        linuxmintrepos
    fi
    if [ "$choice"==3 ]
    then
        asusn13driver
    fi
    if [ "$choice"==4 ]
    then
        standardopenbox
    fi
    if [ "$choice"==5 ]
    then
        xfceopenbox
    fi
    if [ "$choice"==6 ]
    then
        backupstandopenbox
    fi
    if [ "$choice"==7 ]
    then
        backupxfc4openbox
    fi
    echo "You installed: "
    if [ "$choice"==1 ]
    then
        echo "baseinstall"
    fi
    if [ "$choice"==2 ]
    then
        echo "linuxmintrepos"
    fi
    if [ "$choice"==3 ]
    then
        echo asusn13driver
    fi
    if [ "$choice"==4 ]
    then
        echo "standardopenbox"
    fi
    if [ "$choice"==5 ]
    then
        echo "xfceopenbox"
    fi
    if [ "$choice"==6 ]
    then
        echo "backupstandopenbox"
    fi
    if [ "$choice"==7 ]
    then
        echo "backupxfc4openbox"
        echo "If you would like to keep going, type in 1, if not, type in any other number"
    read n
    fi

done

答え1

変える:

if [ "$choice"==1 ]

そして:

if [ "$choice" = 1 ]

すべての後続のテストに対して同じことを行います。

説明する

シェルがそれを見ると、文字列が表示されます"$choice"==1。たとえば、choice2の場合、文字列が表示されます2==1。これは平等テストではありません。文字列です。空ではない文字列なので、テストはtrueを返します。したがって、すべての選択が実行されます。

同等性テストを認識するにはスペースが必要です。

また、小さな点で[スタイルテストの場合、等号はです=。 bashはこれを許可します==が、正しくなく、他のシェルでは機能しません。

[...]コマンドラインでテストを見る

[コマンドラインでテストがどのように機能するかを簡単に探索できます。まず、空の文字列がfalseでテストされていることを示します。

$ if [ "" ]; then echo True; else echo False; fi
False

空でない文字列は何でも真です。

$ if [ abc ]; then echo True; else echo False; fi
True

それでは、見てみましょう2==1

$ if [ 2==1 ]; then echo True; else echo False; fi
True

2==1空ではない文字列なので、テストはtrueです。

それでは、スペースを追加して同等性をテストしましょう。

$ if [ 2 = 1 ]; then echo True; else echo False; fi
False
$ if [ 2 = 2 ]; then echo True; else echo False; fi
True

もう少し微妙に言えば、=ここでは文字列同一性テストが正しく機能します。数値同等性をテストするには、代わりにを使用してください-eq

$ if [ 2 -eq 2 ]; then echo True; else echo False; fi
True

答え2

他の人が述べたように、あなたのif test ...;fi声明は文法的に正確ではありませんが、全体的なアプローチが少し粗雑であることは注目に値します。このスクリプトフローには大幅に改善できるいくつかの側面があります。特に後で読んで編集するのは簡単です。

まず、ループsetで繰り返し選択できますfor。だから可能選ぶそのセレクタはユーザーに通知し、自動的に生成されますが、スクリプトはそれらをすべて文字列リストに入れることができるので、心配する必要はありません。

set --
for c in \
    "Base install:base_fn"                             \
    "Mintrepos:mint_fn"                                \
    "Asusn13 driver:asus_fn"                           \
    "Install Standard openbox:std_obox_fn"             \
    "Install Xfceopenbox:xfce_obox_fn"                 \
    "backing up standard open box config:bkup_fn obox" \
    "backing up openboxfce:bkup_fn xfce"              
do
    set -- "$@" "${c##*:}"
    printf "'%s' = $#\n" "${c%:*}"
done

これは、呼び出しをfn_name位置引数の配列にエンコードし、同時にユーザーフレンドリーな説明を標準出力に出力します。

選択リストを作成し"$@"て進捗状況を印刷したら、read複数回の試行が失敗した後に終了する小さなループでユーザー選択を実行すると同時に入力を検証できます。

chk=$((($#<1)*5))                           #if not at least one choice quit
until [ "$((chk+=1))" -gt 5 ] && exit 1     #chks up to 5 times or quits
printf '\nSelect: '                         #prompts for each try
read -r c && [ -n "${c##*[!0-9]*}" ]        #fails if input not number or empty
do echo "Invalid selection."; done          #prints a notice and retries

shift最後に、不要なパラメータを削除して次を呼び出すことができます$1

shift "$((c-1))"; $1

前にゼロがないことを確認するのが最善です。shiftユーザーが高すぎる数値を選択すると、エラーが発生します。

[ "$((c=$(printf %.d "$c")))" -gt 0 ] || exit 
shift "$((c-1))" && $1

これは、位置配列を非常に便利にする数値選択リスト用です。より一般的には、次のcase文を使用できます。

case "$choice" in
(pattern 1)  do as necessary for a match;;
(pattern 2)  do otherwise for this match;;
(pattern 3)  continue this wise for each;;
(*)          until there isn't a match  ;;
esac 

これは多くのシェルをエミュレートする移植可能な方法にすぎません。(含むbash数年前にselect紹介された声明が提供されます。ksh

からman bash

  • select 名前[in 言葉];do リスト;done
    • 次の単語のリストが展開され、アイテムのリストが生成されます。拡張された単語セットは標準エラーで印刷され、各単語の前に数字が付きます。もし音声で省略された位置パラメータ(または"$@"印刷されます(以下のパラメータを参照)。その後、プロンプトが表示され、$PS3標準入力から1行を読みます。

答え3

になければなりません==。それ以外の場合は、文字列と比較するのではなく、"$choice"==1 文字列自体を渡します。文字列を受け取ると、文字列が空でない限りtrueと評価されます。if$choice1[

$ foo="bar";  [ $foo ] && echo true
true
$ foo="";  [ "$foo" ] && echo true  ## echoes nothing

角かっこの外にtestスペースがない場合、変数は実際に割り当てられます=1。表示するには:

$ f==3
$ echo $f
=3
$ [ 10==12 ] && echo yes
yes

上記のようにf==3変数$f=3

したがって、ifブロックでテストされるのは常にtrueと評価され実行される空でない文字列ですif。これは働きます:

if [ "$choice" == "1" ]
then
    baseinstall
fi

あるいは===文字列比較バッシュから。算術比較をしたい。

if [ "$choice" -eq "1" ]
then
    baseinstall
fi

関連情報