You can simply end a function in a statement, then the return code of the function will be that of the statement itself.
The check [[ $REPLY =~ ^[Yy]$ ]]
looks good. Since you're using the bash built-in double square bracket test, you don't need to quote your variables, since word splitting doesn't happen inside them. Using the regex check is nice, though the simpler glob match with [[ $REPLY = [Yy] ]]
also works.
I guess the main other change I'd make would be to use a local variable in your function and pass it to read
. You can mark it at local
or use declare
which makes variables local when used inside a function.
One last bit is that you might want to consider enabling options errexit
(-e
), nounset
(-u
) and pipefail
in your scripts to make them safer. That would prevent the script from continuing after a failed command and would help to catch typos in variable names. You need to code more defensively in those cases (explicitly testing for error in most of your commands, using defaults for environment variables that may be unset) but it makes for easier debugging when something unexpectedly breaks.
Putting it all together:
#!/bin/bash
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
read -p $'\e[31m\e[1m'"${prompt}"$' [Y/n] \e[0m' -n 1 -r confirm
echo
[[ $confirm =~ ^[Yy]$ ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi
And as @StéphaneChazelas suggests, you could even further improve this to:
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
IFS= read -p $'\e[31;1m'"${prompt}"$' [Y/n] \e[m' -n 1 -r confirm
echo >&2
[[ $confirm = [Yy] ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi
if [[ .. ]]; ... fi; return 1
with just[[ $REPLY = [Yy] ]]
. – mosvy Feb 29 '20 at 13:59zsh
which hasread -q
for that. – Stéphane Chazelas Jun 5 '20 at 16:15