関数の結果を含むWhileループ - BASH

関数の結果を含むWhileループ - BASH

whileループで関数(0または1)の結果を比較したいです。validmask入力した内容がマスク形式であるか確認する機能です。それから私はそれを得ます1。そうでなければ私はそれを得ます0

コマンドを実行して有効なマスクを返すまで、mask=$(whiptail ...)validmask`関数の値を確認したいと思います。$mask with the

私の問題は、関数を再実行できないことです。スクリプトを一度実行した後は終了します。 if文の中に関数を入れなければならないことはわかりますが、どうすればいいのかわかりません。それとも、より良い解決策がありますか?

コードは次のとおりです。

if validmask $mask; then stat2='1'; else stat2='0'; fi
while validmask
do
   if [[ $stat2 == 0 ]]; then
        mask=$(whiptail --title "xx" --inputbox --nocancel "Bad entry" 3>&1 1>&2 2>&3)
   fi
done

次へ追加 関数有効マスク

function validmask()
{
    local  mask=$1
    local  stat2=1

    if [[ $mask =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        OIFS=$IFS
        IFS='.'
        mask=($mask)
        IFS=$OIFS
        [[ ${mask[0]} -le 255 && ${mask[1]} -le 255 \
            && ${mask[2]} -le 255 && ${mask[3]} -le 255 ]]
        stat2=$?
    fi
    return $stat2
}

また、whileループでマスクが有効であることを確認する必要があります。私は持っています以上 if validmask $mask; then stat2='1'; else stat2='0'; fi 空の入力を確認するコードです。

while [[ -z "$mask" ]]
do
   mask=$(whiptail --title "xx" --inputbox --nocancel "Mask" 3>&1 1>&2 2>&3)
done

スクリプトを書き始めると、マスクは一度だけ埋めることができます。関数 validmask は再実行されません。

答え1

最初の質問は次のとおりです。

while validmask
do ...

何も起こりません。パラメータなしで関数を呼び出します。したがって、falseを返し、ループが停止します。

次の質問は関数を実行しますか?~まで返品は有効です。これを行うにはを使用する必要がありますuntil。私は以前これを見落としました。

最初のステートメントを削除し、if次の操作を行う必要があります。

until validmask "$mask"
do    mask=$(get_new_value)
done

Loopはのuntilブール否定ですwhile。実行するコマンドがtrueを返すまで実行されます。

次のように書くこともできます。

while ! validmask "$mask"
do    mask=$(get_new_mask)
done

今課題/試験を完了できます。

unset mask
until validmask "${mask:=$(get_new_value)}"
do    mask=
done

もう一つの問題は、あなたの関数が多くの極端なケースを完全に確認できないことです。validmask特に。[*?case

無効な値を除外してください。

validmask()
    case    "${1##*[!0-9.]*}"       in
    (.*|*.|*..*|*.*.*.*.*|*[!.][!.][!.][!.]*) ! :;;
    (*[3-9][!.][!.]*|*2[6-9][!.]*|*25[6-9]*)  ! :;;
    (*.*.*.*)       ;;              (*)       ! :;;
    esac

小さなデモ:

for mask in              \
         0.0.0.0         \
         0.0.0.          \
         0.0.0.1233      \
         0.0.0.233       \
         0.0..233        \
         0.0.2.233       \
         0.5555.2.233    \
         0.55.2.233      \
         .55.2.233       \
         1.55.2.233      \
         255.255.255.255 \
         255.255.256.255
do    validmask "$mask"
      printf "%-16.16s: %.$?0s%.$((!$?*4))s\n%.d" \
             "$mask" bad good  "0$(($?*8))"
      printf "printf's return:\t $?\n\n"
done  2>/dev/null

0.0.0.0         : good
printf's return:     0

0.0.0.          : bad
printf's return:     1

0.0.0.1233      : bad
printf's return:     1

0.0.0.233       : good
printf's return:     0

0.0..233        : bad
printf's return:     1

0.0.2.233       : good
printf's return:     0

0.5555.2.233    : bad
printf's return:     1

0.55.2.233      : good
printf's return:     0

.55.2.233       : bad
printf's return:     1

1.55.2.233      : good
printf's return:     0

255.255.255.255 : good
printf's return:     0

255.255.256.255 : bad
printf's return:     1

これはvalidmask()実際にマスクを検証する別のバージョンだと思います。ネットマスクがこんなに制限的なのか分からなかった。

validmask()
    case    ."${1##*[!.0124589]*}".      in
    (*.*.*.*.*.*.*|*[!.][!.][!.][!.]*) ! :;;
    (*[!.25]*.[!0]*|*.[!012]*|*0[!.]*) ! :;;
    (*1[!29]*|*1?[!28]*|*98*|*.2?.*)   ! :;;
    (*4[!.08]*|*[.2][25][!245]*)       ! :;;
    (.*.*.*.*.)  echo "$1";; (*)       ! :;;
    esac

a=-1 b=0 c=0 d=0
for o in a b c d
do    while  [ "$(($o+=1))" -lt 1000 ] ||
             ! : "$(($o=255))"
      do     validmask "$a.$b.$c.$d"
done; done

0.0.0.0
128.0.0.0
192.0.0.0
224.0.0.0
240.0.0.0
248.0.0.0
252.0.0.0
254.0.0.0
255.0.0.0
255.128.0.0
255.192.0.0
255.224.0.0
255.240.0.0
255.248.0.0
255.252.0.0
255.254.0.0
255.255.0.0
255.255.128.0
255.255.192.0
255.255.224.0
255.255.240.0
255.255.248.0
255.255.252.0
255.255.254.0
255.255.255.0
255.255.255.128
255.255.255.192
255.255.255.224
255.255.255.240
255.255.255.248
255.255.255.252
255.255.255.254
255.255.255.255

答え2

コマンドを一度実行しwhiptailてマスクを保存します。有効であることを確認し、そうでない場合は、次になるまで繰り返します。

## Get the 1st mask
mask=$(whiptail --title "xx" --inputbox --nocancel "Bad entry" 3>&1 1>&2 2>&3)
## If it isn't valid, repeat until it is
until validmask "$mask"; do
    mask=$(whiptail --title "xx" --inputbox --nocancel "Bad entry" 3>&1 1>&2 2>&3)
done

答え3

あなたの声明をループifに移してください。while

while true
do
   if ! validmask $mask; then
        mask=$(whiptail --title "xx" --inputbox --nocancel "Bad entry" 3>&1 1>&2 2>&3)
   else
       break
   fi
done

関連情報