'How to implement a regex in a if loop bash script?
I am writing a script using a function that is it supposed to install a package by giving to the function the name of the package.
I am asking to the user if he wants to install that packet and, to do so, I wrote a regex, but the thing is: my regex is ignored, I can write anything in the output it will works. Howewer, I want the user to write something specific in order to install the package.
#!/bin/bash
OK=$'\033[92m' #GREEN
BASIC=$'\033[96m' #BLUE
RESET=$'\033[0m' #RESET COLOR
CHECK_MARK=$'\033[0;32m\xE2\x9C\x94\033[0m' #CHECKMARK
function install_package() {
answer=""
while [[ ! ($answer =~ ^y$|Y$|Yes$|YES$|yes$|n$|N$|no$|No$|NO$|q$|Q$|Quit$|quit$) ]]
do
echo -en "${BASIC}Do you want to install $1 ? (y|n|q)${RESET}"
answer=$(read)
if [[ $answer =~ ^y$|Y$|Yes$|YES$|yes$ ]]
echo "test"
then
echo -ne "${OK}Installation of $1 ${RESET}"
apt-get install "$1" -y &>/dev/null
echo -e "\\r${CHECK_MARK}${OK} $1 has been installed or is already installed. ${RESET}"
break
fi
done
}
install_package "micro"
echo "test"
And my output:
root@test-deb:/home/user/bashthings# ./p.sh
Do you want to install micro ? (y|n|q)y
test
✔ micro has been installed or is already installed.
test
root@test-deb:/home/user/bashthings# ./p.sh
Do you want to install micro ? (y|n|q)fege8geg655eg
test
✔ micro has been installed or is already installed.
test
root@test-deb:/home/user/bashthings#
It might be confusing but what I am asking is why my regex is not filtering any of what I type ?
Solution 1:[1]
Use grep -q (or egrep -q for extended version).
# ? your string ? the pattern
if printf %s "my_string" | grep -q '.*stri.*'
then
echo foo
else
echo bar
fi
Your while loop condition will look like this:
while printf %s $answer | grep -q '^y$|Y$|Yes$|YES$|yes$|n$|N$|no$|No$|NO$|q$|Q$|Quit$|quit$'
do
: your loop contents here
done
In your conditions, you do not need to use regular expressions at all. Bash has neat syntax construct called case (similar to C switch):
read -p "${BASIC}Do you want to install $1 ? (y|n|q)${RESET}" answer
case "$answer" in
[yY])
echo -ne "${OK}Installation of $1 ${RESET}"
# […]
echo -e "\\r${CHECK_MARK}${OK} $1 has been installed or is already installed. ${RESET}"
;;
[nN])
: do nothing
;;
[qQ])
exit 0
esac
Case uses simple patterns. y means “exactly y”, you can use [yY] to provide multiple character variants. Separate multiple patterns by | for “or”. Asterisk (*) means “zero or more characters”, question mark (?) is one character.
Note also that I used read -p PROMPT VAR to read a text into a variable while displaying a prompt. See read help for more information, it provides quite a lot of features for reading text in such scripts.
Solution 2:[2]
I'd take advantage of the nocasematch shell option that can compare
strings case-insensitively, and a case statement can add readability:
shopt -s nocasematch
function install_package() {
local package=$1
local answer
while true; do
echo -en "${BASIC}Do you want to install $package ? (y|n|q)${RESET}"
read -r answer
case $answer in
n | no | q | quit)
echo "ok, bye"
exit
;;
y | yes)
echo -ne "${OK}Installation of $package ${RESET}"
#apt-get install "$package" -y &>/dev/null
echo -e "\\r${CHECK_MARK}${OK} $package has been installed or is already installed. ${RESET}"
break
;;
esac
done
}
But the select statement is very useful for these kind of prompts: it
prints a menu and the user selects one of the options. It loops until the user enters a valid value.
function install_package() {
local package=$1
local answer
printf "${BASIC}Do you want to install $package ?${RESET}\n"
PS3="Your answer: "
select answer in Yes No; do
case $answer in
No)
echo "ok, bye"
break
;;
Yes)
echo -ne "${OK}Installation of $package ${RESET}"
#apt-get install "$package" -y &>/dev/null
echo -e "\\r${CHECK_MARK}${OK} $package has been installed or is already installed. ${RESET}"
break
;;
esac
done
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | glenn jackman |
