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

Geo*_*nov 1 linux bash network-interface

我的 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
Run Code Online (Sandbox Code Playgroud)

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

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

ilk*_*chu 8

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

所以,你可以做

[[ "$a" =~ ^"$b"$ ]]
Run Code Online (Sandbox Code Playgroud)

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

但是,由于您只想找到完整匹配项,为什么要使用正则表达式匹配,只需比较相等性即可:

[[ "$a" = "$b" ]]
Run Code Online (Sandbox Code Playgroud)

当然,您的左侧不是单个数组项,而是整个数组。在 item 中找到具有模式匹配的数组中的匹配项有点棘手,此处讨论了在 bash中将大小写和数组一起使用(相对于case,但无论如何都是模式匹配)。

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

[[ "${net_array[*]}" =~ (^| )"$user_iface"( |$) ]]
Run Code Online (Sandbox Code Playgroud)

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


但我只会遍历数组元素并检查匹配项:

found=0
for a in "${net_array[@]}" ; do
     [[ "$a" = "$user_iface" ]] && found=1
done
Run Code Online (Sandbox Code Playgroud)

或者把循环放在一个函数中:

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

然后整个要求输入的东西就像这样

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
Run Code Online (Sandbox Code Playgroud)

...或者只是使用select并保存用户一些输入:

select choice in "${net_array[@]}" ; do 
    if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
Run Code Online (Sandbox Code Playgroud)

(它循环直到你break退出)