Whileループ内の関数の結果(0または1)を比較したいと思います。関数validmask
は、入力された入力がマスク形式であるかどうかをチェックします。もしそうなら私は_1
_を取得し、そうでなければ私は_0
_を取得します。
mask=$(whiptail ...)
コマンドを実行し、有効なマスクが返されるまで_$mask with the
_ validmask`関数の値を確認したいと思います。
私の問題は、関数を再度実行できないことです。スクリプトは1回実行すると終了します。関数を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
_
[〜#〜]追加[〜#〜]関数validmask
_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
}
_
また、ループ中は、マスクが有効かどうかを確認する必要があります。空の入力をチェックする上記 _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
_
スクリプトを開始すると、マスクを1回だけ入力できます。関数validmaskは再度実行されません。
whiptail
コマンドを1回実行して、マスクを保存するだけです。有効かどうかを確認し、有効でない場合は、次のようになるまで繰り返します。
## 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
あなたの最初の問題は:
_while validmask
do ...
_
そこでは何も起こりません-引数なしで関数を呼び出します。そして、それはfalseを返し、ループが停止します。
次の問題は、関数を実行することですntil戻り値は有効です。そのためには、until
を使用する必要があります。私は以前これをなんとか見落としていました。
最初のif
ステートメントを削除して、次の操作を行う必要があります。
_until validmask "$mask"
do mask=$(get_new_value)
done
_
until
ループは、while
のブール否定です。実行するコマンドがtrueを返すまで実行されます。
それはまた書くことができます:
_while ! validmask "$mask"
do mask=$(get_new_mask)
done
_
あなたはすぐに割り当て/テストを行うかもしれません:
_unset mask
until validmask "${mask:=$(get_new_value)}"
do mask=
done
_
もう1つの問題は、validmask
関数が、多くのEdgeケース(特に_[*?
_を含むケース)に対して完全に検証できないことです。 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
_
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