while 检查变量是否在数组 bash 中

while 检查变量是否在数组 bash 中

我的 while 循环检查中有一个错误。我正在检查用户输入是否是有效的用户界面。这是我的代码:

#!/bin/bash

net_array=()
for iface in $(ifconfig | cut -d ' ' -f1| tr ':' '\n' | awk NF)
do
        net_array+=("$iface")
done
unset "net_array[${#net_array[@]}-1]"

# Network Interface selection

printf "\nPlease select the network interface you want to use:\n"
read -r user_iface

while ! [[ "${net_array[@]}" =~ $user_iface ]]; do # check if the user input is valid
        echo "Please enter a valid network interface:"
        read -r user_iface
done

通常,此代码可以工作并检查该元素是否在数组中。我的电脑有 eno1、eno2、eno3 接口,当我插入不同的东西(如 eno5)时,它会再次要求我插入网络接口。

问题是,如果我只插入1,它会接受它作为有效的网络接口,但事实并非如此,我想排除它。我想我可以执行额外的检查,排除所有数字用户输入,但我想知道我的错误是什么?

答案1

正则表达式匹配[[ string =~ pattern ]]实际上并不匹配完整字符串,但是搜索对于字符串中的模式(如grep)。您需要使用^$特殊字符(“锚点”)将模式锁定到行的开头和结尾。

所以,你可以这样做

[[ "$a" =~ ^"$b"$ ]]

引用变量,以便其内容不被视为正则表达式。

不过,既然您只想找到完整的匹配项,为什么要使用正则表达式匹配,只需比较相等性:

[[ "$a" = "$b" ]]

当然,您的左侧不是单个数组项,而是整个数组。在 item 数组中查找具有类似模式匹配的匹配有点棘手,这里已讨论过在 bash 中一起使用大小写和数组(与 相关case,但无论如何都是模式匹配)。

简而言之,您可以执行以下操作,搜索两侧带有空格或字符串开头/结尾的所选项目:

[[ "${net_array[*]}" =~ (^| )"$user_iface"( |$) ]]

只要用户不输入任何空格,它就应该起作用,尽管我们当然可以更改IFS以获得另一个分隔符。


但我只是循环遍历数组元素并检查是否匹配:

found=0
for a in "${net_array[@]}" ; do
     [[ "$a" = "$user_iface" ]] && found=1
done

或者将循环放入函数中:

contains() {
        typeset _x;
        typeset -n _A="$1"
        for _x in "${_A[@]}" ; do
                [ "$_x" = "$2" ] && return 0
        done
        return 1
}

然后整个请求输入的事情就会像这样

while read -p "please enter a network interface: " -r user_iface; 
      ! contains net_array "$user_iface" ; do
    echo "$user_iface is not a valid interface!"
done

...或者只是使用select并节省用户的一些输入:

select choice in "${net_array[@]}" ; do 
    if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";

(循环播放直到你break退出)

相关内容