Home > database >  How to implement a regex in a if loop bash script?
How to implement a regex in a if loop bash script?

Time:03-10

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 ?

CodePudding user response:

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.

CodePudding user response:

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
}
  • Related