比較演算子を使用できますか?

比較演算子を使用できますか?

電流量、距離(フィート)、許容電圧降下を考慮して必要な電線ゲージを計算する関数を構築しています。

この値が与えられたら、「円形小麦」を計算することができ、そこから次のようになります。AWGの要件。私は丸い小麦を彼らの尊敬された仕様と比較する大きな声明を作り始めましたが、これは正しいツールだとif elif思います。case

数字を比較するケースが見つからなかったので、次のようにできるかどうか疑問に思います。

what.gauge () {

    let cmils=11*2*$1*$2/$3
    let amils=17*2*$1*$2/$3


    case $cmils in

        320-403)
            cawg="25 AWG"
            ;;
        404-509)
            cawg="24 AWG"
            ;;
        510-641)
            cawg="23 AWG"
            ;;

        etc...

}

答え1

POSIXシェル

算術テストを探していますが、ケースは算術を実行しないので、これはif-then自然なアプローチのようです。

if [ "$cmils" -lt 320 ]
then
        cawg="??"
elif [ "$cmils" -le 403 ]
then
        cawg="25 AWG"
elif [ "$cmils" -le 509 ]
then
        cawg="24 AWG"
elif [ "$cmils" -le 641 ]
then
        cawg="23 AWG"
fi

クリティカルのみ発生

私はポータブルソリューションを好むが、一部の人々はbashの算術構文が好きです。

if ((cmils < 320))
then
        cawg="??"
elif ((cmils <= 403))
then
        cawg="25 AWG"
elif ((cmils <= 509))
then
        cawg="24 AWG"
elif ((cmils <= 641))
then
        cawg="23 AWG"
fi

POSIX構文よりも強力ですが、脆弱です。理由を理解するには、設定後にこのコードを試してくださいcmils=cmils

答え2

case $cmils in

    3[2-9][0-9]|40[0-3])
        cawg="25 AWG"
        ;;
    40[4-9]|4[1-9][0-9]|50[0-9])
        cawg="24 AWG"
        ;;
    51[0-9]|6[0-3][0-9]|64[01])
        cawg="23 AWG"
        ;;

答え3

他の人が言ったように、caseこの比較演算子はサポートされておらず、グローバルパターン一致のみがサポートされています。

ただし、if/elif/fiステートメントセットを作成できます。バラよりケースの説明と似ていますが、形式が異なります。たとえば、John1024の答えに基づいて、次のようになります。

if   [ "$cmils" -lt 320 ]; then cawg='??'
elif [ "$cmils" -le 403 ]; then cawg='25 AWG'
elif [ "$cmils" -le 509 ]; then cawg='24 AWG'
elif [ "$cmils" -le 641 ]; then cawg='23 AWG'
fi

でも:

[ "$cmils" -ge 320 ] && [ "$cmills" -le 403 ] && cawg='25 AWG'
[ "$cmils" -ge 404 ] && [ "$cmills" -le 509 ] && cawg='24 AWG'
[ "$cmils" -ge 510 ] && [ "$cmills" -le 641 ] && cawg='23 AWG'

メモ:この変形の欠点は、使用されたものとは異なり、elif少なくとも各行の最初のテストが実行されることです。elifテストがtrueと評価された後、を使用すると、残りのテストはすべてスキップされます。そのようなものを関数に入れて&& return設定した後に追加できますcawg

私は個人的に2つのうちの1つがより読みやすくなると思いますが(追加の改行や交互にインデントすることによって状況が複雑になることはありません)、この特定のコーディングスタイル/インデントの問題に関する意見は非常に多様です。 :)

すべての項目が同じ(または非常に近い)列に配置されるため、コピー、貼り付け、編集も簡単です。実際のエディタを使用するときに便利です。

答え4

値を範囲にマップしてから、ステートメントでその範囲のインデックス番号を使用できますcase

cmil_limits=(320 404 510 642)
index=0
for limit in "${cmil_limits[@]}"
do
        if [ "$cmils" -lt "$limit" ]
        then
                break
        fi
        ((index++))
done
case "$index" in
   0)                   # < 320
        cawg="??"
        ;;
   1)                   # 320-403
        cawg="25 AWG"
        ;;
   2)                   # 404-509
        cawg="24 AWG"
        ;;
   3)                   # 510-641
        cawg="23 AWG"
        ;;
   4)                   # > 641
        cawg="??"
        ;;
esac

$cmils320未満の場合、を使用forして最初の反復でループを終了しますindex=0。  $cmils≮320(つまり≥320)の場合は増分index(→ 1)し、次の繰り返しを続けます。その後、$cmils<404(つまり整数であると仮定すると≤403)の場合はループを終了しますindex=1。など。 ≮642の場合は$cmils≥642なので> 641なので、ループの最後まで実行してをfor得ますindex=4

これの利点は、カットオフをすべて同じ行に維持し、重複番号を維持する必要がないことです(たとえば、現在のコードと他の回答コードの両方に403をリストします)。そして404、同時に509そして510 - これは重複し、番号が変更されると、より多くのメンテナンスが必要です。これが現実世界の関心事なのかは分かりません。 )


cmil_limits配列です。 bash、ksh、および他の一部のシェルは配列をサポートしていますが、一部はそうではありません。配列をサポートしていないシェルで同様の作業を行う必要がある場合は、リストをステートメントに直接配置できますfor

for limit in 320 404 510 642
do

または、シェルの引数リストを配列として使用します。

set -- 320 404 510 642
for limit in "$@"
do

一部のシェルでは上記の内容を短縮できます。

set -- 320 404 510 642
for limit
do

((…))算術は bashism の一形態でもあります(let声明に示すように)。 arithmetic をサポートしていないシェルで同様の作業を行う必要がある場合は、次のものを置き換えることができます((…))

        ((index++))

文(増加index

        index=$(expr "$index" + 1)

前後のスペースは+必須です。

関連情報