带有函数结果的 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

添加 函数 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
}

另外,在循环 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

循环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

相关内容