I have a script that substitutes a variable with another value, depending on the input:
#!/bin/bash
prompt()
{
while true; do
read -p "Do you wish to install this program? " "ANSWER"
case "$ANSWER" in
[Yy]* ) printf -v "$1" %s "true"; break;;
[Nn]* ) printf -v "$1" %s "false"; break;;
* ) echo "Please answer yes or no.";;
esac
done
}
prompt "QUESTION"
if [ "$QUESTION" = "true" ]; then
echo "SUCCESS"
elif [ "$QUESTION" = "false" ]; then
echo "FAILURE"
fi
This works fine, though i want the script to be POSIX compliant. I use #!/bin/sh for all my scripts, though printf -v is bashism. How can i modify this program? Is there an equivalent function i could use? Thanks!
read itself can set the variable whose name is in $1. However, you still need read ANSWER first, so that you can examine the response. Once it's done, you can use read and a here-document to transfer the value of $ANSWER to whatever variable prompt requests.
prompt () {
while :; do
printf "Do you wish to install this program? " >&2
read ANSWER
case $ANSWER in
[Yy]* ) ANSWER=true ; break ;;
[Nn]* ) ANSWER=false; break ;;
* ) printf 'Please answer yes or no.\n' >&2 ;;
esac
done
read "$1" <<EOF
$ANSWER
EOF
}
You can use a command substitution to ensure the ANSWER is not set in the global environment.
prompt () {
read "$1" <<EOF
$(while :; do
printf "Do you wish to install this program? " >&2
read ANSWER
case $ANSWER in
[Yy]* ) printf true; break ;;
[Nn]* ) printf false; break ;;
* ) printf 'Please answer yes or no.\n' >&2 ;;
esac
done
)
EOF
}
Related
I've an question, how to use *if *or *case * statements to do below command :
command.sh --value string ?
I tried :
case "$1" in
[--value ])
echo "You choose value"
;;
*)
echo "plz chs diff one"
;;
esac
But it is not what I want to achieve.
I want to run command.sh --value string , where string is the first argument.
getopts is a tool that can be used to parse arguments
usage() {
echo "Usage: $0 [-v]" 1>&2
}
exit_abnormal() {
usage
exit 1
}
while getopts "v" arg; do
case $arg in
v) USE_VALUE='true' ;;
?)
echo "Invalid option: -${OPTARG}."
echo
usage
;;
esac
done
shift
if [[ $USE_VALUE == "true" ]]; then
...
fi
You can try this:
if [ "$1" = "--value" ]; then
echo "You choose value $2"
else
echo "plz chs diff one"
fi
I have a very simple BASH script that asks the user if they would like to enter some input. The response is y or n
If they enter n the script exits.
If they enter y then they are asked some questions. At the end I want to ask them to confirm the input.
If it's correct we'll carry on, if not I want to return them to the questions to re enter the information.
So far I've got:
while true; do
echo -e "Enter details ? "
read yn
case $yn in
[Nn]* ) exit;;
[Yy]* )
echo -e "description"
read desc
echo -e "Address"
read address
* ) echo "Please answer yes or no.";;
esac
done
This seems to work fine, so I've tried to add the confirmation.. but thats not working.
while true; do
echo -e "Enter details ? "
read yn
case $yn in
[Nn]* ) exit;;
[Yy]* )
echo -e "description"
read desc
echo -e "Address"
read address
echo -e "$desc - $address"
while true; do
echo -e "\nAre these details correct ? "
read conf
case $conf in
[Nn]* ) // return to enter details //
[Yy]* ) // carry on with the details entered // break;;
esac
done
* ) echo "Please answer yes or no.";;
esac
done
The aim is as follows
The user selects y and enters description and address. The page shows them a summary of what they've entered and asks them are these details correct ? if they are we move on and the script progresses. The the input is wrong then the script returns them to enter description followed by enter address.
Can someone advise how to do this.
Thanks
You could add one more loop level and use the optional level indicator of break [n]:
while true; do
echo -e "Enter details ? "
read yn
case $yn in
[Nn]*) exit;;
[Yy]*)
while true; do
echo -e "description"
read desc
echo -e "Address"
read address
echo -e "$desc - $address"
while true; do
echo -e "\nAre these details correct ? "
read conf
case $conf in
[Nn]* ) break 1;;
[Yy]* ) break 3;;
esac
done
done;;
*) echo "Please answer yes or no.";;
esac
done
Don't use case for this.
Script for example for you:
#!/bin/bash
while true; do
echo -e "Enter details ?(y/n)"
read yn
if [[ $yn == "y" ]];then
echo -e "description"
read desc
echo -e "Address"
read address
echo -e "$desc - $address"
while true; do
echo -e "\nAre these details correct ? (y/n)"
read conf
if [[ $conf == "y" ]];then
echo "All done"
break
elif [[ $conf == "n" ]];then
break
else
continue
fi
done
elif [[ $yn == "n" ]];then
break
else
continue
fi
There you go:
DONE=""
while [ "$DONE" != "true" ]; do
echo -e "Enter details ? "
read yn
case $yn in
[Nn]* ) exit;;
[Yy]* )
echo -e "description"
read desc
echo -e "Address"
read address
echo -e "$desc - $address"
while true; do
echo -e "\nAre these details correct ? "
read conf
case $conf in
[Nn]* )
break;;
[Yy]* )
echo "doing something with your values"
DONE="true"
break;;
esac
done
;;
* ) echo "Please answer yes or no.";;
esac
done
I am running the below script, but it looks like the $filename or $srvname did not get the input value.
say for eg: ./test.sh -n abcd.net gives the output echo 'Filename or node name must be defined.'
it means that, the $srvname did not get the value "abcd.net", please advise am i doing anything wrong. ?
set -x
usage () {
echo "usage: $0 -n <nodename>"
echo "usage: $0 -f <filename>"
echo "usage: $0 -h <help>"
}
while getopts ":nfh:" opt; do
case "$opt" in
n) srvname="$OPTARG" ;;
f) filename="$OPTARG" ;;
h) # help
usage
exit 0
;;
:) echo "Error: -$OPTARG requires an argument"
usage
exit 1
;;
?) echo "Error: unknown option -$OPTARG"
usage
exit 1
;;
esac
done
function dosomecheck {
echo "do some checks"
}
if [ "$filename" != "" ] ; then
# read file
for x in `cat $filename` ; do
dosomecheck $x
done
fi
if [ "$srvname" != "" ] ; then
# read file
for x in $srvname ; do
dosomecheck $x
done
fi
Thanks in advance
Try doing:
while getopts ":n:f:h" opt;
because -n and -f takes argument while -h doesn't.
I have a script with several inputs, the script eventually initiates a download, once the download is complete i would like to do prompt the user to start the process over if they want to download something else.
while true;do
read -p "Is this correct? (yes/no/abort) " yno
case $yno in
[Yy]*) break;;
[Nn]*) echo "Lets Start Over" 'restart script code goes here';;
[Aa]*) exit 0;;
*) echo "Try again";;
esac
done
echo
echo "Starting $build download for $opt1 from Jenkins"
echo
while true;do
read -p "Do you want to download something else? " yesno
case $yesno in
[Yy]* ) 'restart script code goes here';;
[Nn]* ) break;;
* ) echo "Try Again "
esac
done
If you design your shell script with shell functions, repeating a chunk of code gets much easier:
main() {
while true; do
next
if ! validate_opt 'Do you want to download something else?'; then
break
fi
done
}
validate_opt() {
local PS3="$1 (Press ctrl-c to exit) "
local choice
select choice in yes no; do
# This can be written more tersely,
# but for clarity...
case $choice in
yes) return 0;;
no) return 1;;
esac
done
}
do_download() {
echo
echo "Starting $build download for $opt1 from Jenkins"
echo
fetch "$1" # or whatever
}
next() {
if validate_opt 'Is this correct?'; then
do_download "$opt"
else
echo "Let's start over"
fi
}
main
function stage1 {
while true;do
read -p "Is this correct? (yes/no/abort) " yno
case $yno in
[Yy]*) stage2;;
[Nn]*) continue;;
[Aa]*) exit 0;;
*) echo "Try again";;
esac
done
}
function stage2 {
echo
echo "Starting $build download for $opt1 from Jenkins"
echo
while true;do
read -p "Do you want to download something else? " yesno
case $yesno in
[Yy]* ) stage1;;
[Nn]* ) exit 0;;
* ) echo "Try Again ";;
esac
done
}
stage1
You can do this using functions
The first function is stage 1 and the second stage2
After listing all the functions, at the bottom of the file we call stage1.
when the function stage1 executes and $yno= Y* or y* , it will skip to the stage2 function, vice versa when we in stage2
I have one problem , when i select one option , for exemple ./test.sh -f it should print "mel" but it reads all code.
How does it enter the if condition and passes with other argument ?
if getopts :f:d:c:v: arg ; then
if [[ "${arg}" == d ]] ; then
d_ID=$OPTARG
eval d_SIZE=\$$OPTIND
else
echo "Option -d argument missing: needs 2 args"
echo "Please enter two args: <arg1> <arg2>"
read d_ID d_SIZE
echo "disc $d_ID $d_SIZE" >> $FILENAME
fi
if [[ "${arg}" == c ]] ; then
c_NOME="$OPTARG"
eval c_ID1=\$$OPTIND
eval c_ID2=\$$OPTINDplus1
eval c_FICHEIRO=\$$OPTINDplus2
else
echo "Option -c argument missing: needs 4 args"
echo "Please enter two args: <arg1> <arg2> <arg3> <agr4>"
read c_NOME c_ID1 c_ID2 c_FICHEIRO
echo "raidvss $c_NOME $c_ID1 $c_ID2 $c_FICHEIRO" >> $FILENAME
fi
if [[ "${arg}" == f ]] ; then
echo "mel"
fi
fi
You are using getopts parameters wrong.
if getopts :f:d:c:v: arg
means that -f will follow the value of parameter, like
-f 5
If you want just have -f (without value) you need to change it to
if getopts :fd:c:v: arg ; then
(I deleted the ':'). Also, I think you should better use while cycle and case statements.
See this example
while getopts fd:c:v: opt
do
case "$opt" in
f) echo "mel";;
d) discFunction "$OPTARG";;
c) otherFunction "$OPTARG";;
v) nop;;
\?) echo "$USAGE" >&2; exit 2;;
esac
done
shift `expr $OPTIND - 1`