while check if a variable is in an array bash
Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
I have a bug in my while loop check. I am checking if the user input is a valid user interface. This is my code:
#!/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
Generally this code works and checks if the element is in the array. My PC has eno1, eno2, eno3 interfaces and when I insert something different like eno5 it asks me again to insert the network interface.
The problem is that if I insert only 1
, it accepts it as a valid network interface, which is not the case and I want to exclude it. I guess I can perform additional check excluding all numerical user inputs, but I am wondering what my error is?
linux bash network-interface
add a comment |Â
up vote
0
down vote
favorite
I have a bug in my while loop check. I am checking if the user input is a valid user interface. This is my code:
#!/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
Generally this code works and checks if the element is in the array. My PC has eno1, eno2, eno3 interfaces and when I insert something different like eno5 it asks me again to insert the network interface.
The problem is that if I insert only 1
, it accepts it as a valid network interface, which is not the case and I want to exclude it. I guess I can perform additional check excluding all numerical user inputs, but I am wondering what my error is?
linux bash network-interface
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have a bug in my while loop check. I am checking if the user input is a valid user interface. This is my code:
#!/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
Generally this code works and checks if the element is in the array. My PC has eno1, eno2, eno3 interfaces and when I insert something different like eno5 it asks me again to insert the network interface.
The problem is that if I insert only 1
, it accepts it as a valid network interface, which is not the case and I want to exclude it. I guess I can perform additional check excluding all numerical user inputs, but I am wondering what my error is?
linux bash network-interface
I have a bug in my while loop check. I am checking if the user input is a valid user interface. This is my code:
#!/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
Generally this code works and checks if the element is in the array. My PC has eno1, eno2, eno3 interfaces and when I insert something different like eno5 it asks me again to insert the network interface.
The problem is that if I insert only 1
, it accepts it as a valid network interface, which is not the case and I want to exclude it. I guess I can perform additional check excluding all numerical user inputs, but I am wondering what my error is?
linux bash network-interface
asked Dec 23 '17 at 8:38
Georgõ Stoyanov
16515
16515
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
6
down vote
The regex match [[ string =~ pattern ]]
doesn't actually match against the full string, but searches for the pattern in the string (like grep
). You'd need to lock the pattern to the beginning and end of line, with the ^
and $
special characters ("anchors").
So, you could do
[[ "$a" =~ ^"$b"$ ]]
quoting the variable so that its contents are not taken as a regex.
Though, since you only want to find full matches, why use a regex match at all, just compare for equality:
[[ "$a" = "$b" ]]
Except that of course your left hand side wasn't a single array item, but the whole array. Finding a matching in item an array with a pattern match like that is somewhat tricky, it was discussed here Using case and arrays together in bash (in relation to case
, but a pattern match anyway).
In brief, you could do something like this, searching for the chosen item with a space or start/end of string on both sides:
[[ "$net_array[*]" =~ (^| )"$user_iface"( |$) ]]
It should work as long as the user doesn't enter any whitespace, though we could of course change IFS
to get another separator.
But I would just loop over the array elements and check for a match:
found=0
for a in "$net_array[@]" ; do
[[ "$a" = "$user_iface" ]] && found=1
done
Or put the loop in a function:
contains()
typeset _x;
typeset -n _A="$1"
for _x in "$_A[@]" ; do
[ "$_x" = "$2" ] && return 0
done
return 1
and then the whole asking for input thing would something like this
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
... or just use select
and save the users some typing:
select choice in "$net_array[@]" ; do
if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
(it loops until you break
out)
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
The regex match [[ string =~ pattern ]]
doesn't actually match against the full string, but searches for the pattern in the string (like grep
). You'd need to lock the pattern to the beginning and end of line, with the ^
and $
special characters ("anchors").
So, you could do
[[ "$a" =~ ^"$b"$ ]]
quoting the variable so that its contents are not taken as a regex.
Though, since you only want to find full matches, why use a regex match at all, just compare for equality:
[[ "$a" = "$b" ]]
Except that of course your left hand side wasn't a single array item, but the whole array. Finding a matching in item an array with a pattern match like that is somewhat tricky, it was discussed here Using case and arrays together in bash (in relation to case
, but a pattern match anyway).
In brief, you could do something like this, searching for the chosen item with a space or start/end of string on both sides:
[[ "$net_array[*]" =~ (^| )"$user_iface"( |$) ]]
It should work as long as the user doesn't enter any whitespace, though we could of course change IFS
to get another separator.
But I would just loop over the array elements and check for a match:
found=0
for a in "$net_array[@]" ; do
[[ "$a" = "$user_iface" ]] && found=1
done
Or put the loop in a function:
contains()
typeset _x;
typeset -n _A="$1"
for _x in "$_A[@]" ; do
[ "$_x" = "$2" ] && return 0
done
return 1
and then the whole asking for input thing would something like this
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
... or just use select
and save the users some typing:
select choice in "$net_array[@]" ; do
if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
(it loops until you break
out)
add a comment |Â
up vote
6
down vote
The regex match [[ string =~ pattern ]]
doesn't actually match against the full string, but searches for the pattern in the string (like grep
). You'd need to lock the pattern to the beginning and end of line, with the ^
and $
special characters ("anchors").
So, you could do
[[ "$a" =~ ^"$b"$ ]]
quoting the variable so that its contents are not taken as a regex.
Though, since you only want to find full matches, why use a regex match at all, just compare for equality:
[[ "$a" = "$b" ]]
Except that of course your left hand side wasn't a single array item, but the whole array. Finding a matching in item an array with a pattern match like that is somewhat tricky, it was discussed here Using case and arrays together in bash (in relation to case
, but a pattern match anyway).
In brief, you could do something like this, searching for the chosen item with a space or start/end of string on both sides:
[[ "$net_array[*]" =~ (^| )"$user_iface"( |$) ]]
It should work as long as the user doesn't enter any whitespace, though we could of course change IFS
to get another separator.
But I would just loop over the array elements and check for a match:
found=0
for a in "$net_array[@]" ; do
[[ "$a" = "$user_iface" ]] && found=1
done
Or put the loop in a function:
contains()
typeset _x;
typeset -n _A="$1"
for _x in "$_A[@]" ; do
[ "$_x" = "$2" ] && return 0
done
return 1
and then the whole asking for input thing would something like this
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
... or just use select
and save the users some typing:
select choice in "$net_array[@]" ; do
if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
(it loops until you break
out)
add a comment |Â
up vote
6
down vote
up vote
6
down vote
The regex match [[ string =~ pattern ]]
doesn't actually match against the full string, but searches for the pattern in the string (like grep
). You'd need to lock the pattern to the beginning and end of line, with the ^
and $
special characters ("anchors").
So, you could do
[[ "$a" =~ ^"$b"$ ]]
quoting the variable so that its contents are not taken as a regex.
Though, since you only want to find full matches, why use a regex match at all, just compare for equality:
[[ "$a" = "$b" ]]
Except that of course your left hand side wasn't a single array item, but the whole array. Finding a matching in item an array with a pattern match like that is somewhat tricky, it was discussed here Using case and arrays together in bash (in relation to case
, but a pattern match anyway).
In brief, you could do something like this, searching for the chosen item with a space or start/end of string on both sides:
[[ "$net_array[*]" =~ (^| )"$user_iface"( |$) ]]
It should work as long as the user doesn't enter any whitespace, though we could of course change IFS
to get another separator.
But I would just loop over the array elements and check for a match:
found=0
for a in "$net_array[@]" ; do
[[ "$a" = "$user_iface" ]] && found=1
done
Or put the loop in a function:
contains()
typeset _x;
typeset -n _A="$1"
for _x in "$_A[@]" ; do
[ "$_x" = "$2" ] && return 0
done
return 1
and then the whole asking for input thing would something like this
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
... or just use select
and save the users some typing:
select choice in "$net_array[@]" ; do
if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
(it loops until you break
out)
The regex match [[ string =~ pattern ]]
doesn't actually match against the full string, but searches for the pattern in the string (like grep
). You'd need to lock the pattern to the beginning and end of line, with the ^
and $
special characters ("anchors").
So, you could do
[[ "$a" =~ ^"$b"$ ]]
quoting the variable so that its contents are not taken as a regex.
Though, since you only want to find full matches, why use a regex match at all, just compare for equality:
[[ "$a" = "$b" ]]
Except that of course your left hand side wasn't a single array item, but the whole array. Finding a matching in item an array with a pattern match like that is somewhat tricky, it was discussed here Using case and arrays together in bash (in relation to case
, but a pattern match anyway).
In brief, you could do something like this, searching for the chosen item with a space or start/end of string on both sides:
[[ "$net_array[*]" =~ (^| )"$user_iface"( |$) ]]
It should work as long as the user doesn't enter any whitespace, though we could of course change IFS
to get another separator.
But I would just loop over the array elements and check for a match:
found=0
for a in "$net_array[@]" ; do
[[ "$a" = "$user_iface" ]] && found=1
done
Or put the loop in a function:
contains()
typeset _x;
typeset -n _A="$1"
for _x in "$_A[@]" ; do
[ "$_x" = "$2" ] && return 0
done
return 1
and then the whole asking for input thing would something like this
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
... or just use select
and save the users some typing:
select choice in "$net_array[@]" ; do
if [[ "$choice" ]]; then break; else echo "invalid choice!"; fi;
done;
echo "you chose $choice";
(it loops until you break
out)
edited Dec 23 '17 at 10:35
answered Dec 23 '17 at 9:40
ilkkachu
49.9k674137
49.9k674137
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f412641%2fwhile-check-if-a-variable-is-in-an-array-bash%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password