我的 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
退出)