enquanto verifica se uma variável está em uma matriz

0

Eu tenho um bug na minha verificação while loop. Estou verificando se a entrada do usuário é uma interface de usuário válida. Este é o meu código:

#!/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

Geralmente este código funciona e verifica se o elemento está na matriz. Meu PC tem eno1, eno2, eno3 interfaces e quando insiro algo diferente como eno5 ele me pede novamente para inserir a interface de rede.

O problema é que, se eu inserir apenas 1 , ele aceita como uma interface de rede válida, o que não é o caso e eu quero excluí-lo. Eu acho que posso realizar uma verificação adicional, excluindo todas as entradas numéricas do usuário, mas estou querendo saber qual é o meu erro?

    
por Georgе Stoyanov 23.12.2017 / 09:38

1 resposta

6

A correspondência de regex [[ string =~ pattern ]] na verdade não corresponde à string completa, mas procura pelo padrão na string (como grep ). Você precisaria bloquear o padrão no início e no final da linha, com os caracteres ^ e $ especiais ("âncoras").

Então, você poderia fazer

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

citando a variável para que seu conteúdo não seja tomado como regex.

No entanto, como você só quer encontrar correspondências completas, por que usar uma correspondência regular, apenas compare por igualdade:

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

Só que, claro, o seu lado esquerdo não era um único item da matriz, mas todo o array. Encontrar um item correspondente em uma matriz com uma correspondência de padrão como essa é um pouco complicado, foi discutido aqui Usando case e arrays juntos em bash (em relação a case , mas uma correspondência de padrões de qualquer maneira).

Em resumo, você poderia fazer algo parecido com isso, procurando o item escolhido com um espaço ou início / fim da string em ambos os lados:

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

Ele deve funcionar enquanto o usuário não inserir nenhum espaço em branco, embora possamos alterar o IFS para obter outro separador.

Mas eu passaria os elementos da matriz e verificaria uma correspondência:

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

Ou coloque o loop em uma função:

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

e, em seguida, todo o pedido de entrada seria algo como isto

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

... ou apenas use select e salve os usuários digitando:

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

(faz um loop até você break out)

    
por 23.12.2017 / 10:40