Bash programming looping in if and case statement - bash

Why is it the code on "if" statement will keep looping if null is input to "title" variable but for the case statement, my script will have error?
echo -n "Title :"
read title
if [ -z "$title" ]; then
echo "Please input a title"
while [[ -z "$title" ]] ; do
echo -n "Title: "
read title
done
fi
read author
case "$author" in
*[0-9,\""\!##$%\(\)]*) echo "Please enter a name" ;;
while *[1-9,\""\!##$%\(\)]*)"$author" ]] ; do
echo -n "author "
read author
esac

The line
while *[1-9,\""\!##$%\(\)]*)"$author" ]] ; do
wouldn't be allowed there even if there weren't a bunch a syntax errors in it. Try this idiom instead:
title=
while [ -z "$title ]
do
read -p "What is the title? " title
done

You have \"" and should be only \" . That's the syntax error
Also, you can't put a While as a case. Try this and add any cases you want
while [ -z $author ]; do
echo "Please enter an author: "
read author
case "$author" in
*[0-9,\"\!##$%\(\)]*) echo "First case - $author"
;;
esac
done

Related

if else condition in shell script to check empty input by user

I am taking input from the user, and wants that if user give empty input , it should display the error message , I am trying below code , please correct me where I am wrong .
#!/bin/bash
echo "please enter previous version number"
read prevversion
echo "please enter new version number"
read newversion
echo "please enter environment [DEV2/QAT2/PPE2/PRD]"
read env
if[["$env"=" " &&"$prevversion"=" " &&"$newversion"= " "]]
then
echo "Please enter the details and try again"
else
if [ "$env" = "QAT2" ]
then
prevversion="$prevversion"_QAT2
echo "previous version is $prevversion"
newversion="$newversion"_QAT2
echo "new version is $newversion"
env="$env"
echo "enviornment is $env"
elif [ "$env" = "PPE2" ]
then
prevversion="$prevversion"
echo "previous version is $prevversion"
newversion="$newversion"
echo "new version is $newversion"
env="$env"
echo "enviornment is $env"
elif [ "$env" = "PRD" ]
then
prevversion="$prevversion"
echo "previous version is $prevversion"
newversion="$newversion"
echo "new version is $newversion"
env="$env"
echo "enviornment is $env"
elif [ "$env" = "DEV2" ]
then
prevversion="$prevversion"_DEV2
echo "previous version is $prevversion"
newversion="$newversion"_DEV2
echo "new version is $newversion"
env="$env"
echo "enviornment is $env"
fi
fi
please provide me with correct solution
your are using '&&' in your if-condition which means, that the error-message is only displayed when every(!) input is empty:
if[["$env"=" " &&"$prevversion"=" " &&"$newversion"= " "]]
You should change it like that:
if [ -z "${env}" ] || [ -z "${prevversion}" ] || [ -z "${newversion}" ]; then
echo "either one of the vars is empty"
exit 1
fi
You need to use ||, not &&. And you should be testing against an empty string, not a string with a single space.
if [[ "$env" = "" || "$prevversion" = "" || "$newversion" = "" ]]
Change your code in the following way:
if [ -z "$env" ] || [ -z "$prevversion" ] || [ -z "$newversion" ]; then
echo "either one of the vars is empty"
exit 1
fi
this will check that at least one of the tree var is empty.
If this is the case print your error message and exit the script with return code 1 to show that the script exit in error.
Use -z to check for an empty string, and don't repeat so much code.
#!/bin/bash
# Prompt for what should be command line arguments. If
# the script is going to be used in a batch environment to read
# from a stream, then prompting is unhelpful. If it is used
# in an interactive environment, it is easier to pass this
# data on the command line.
echo "please enter previous version number"
read prevversion
echo "please enter new version number"
read newversion
echo "please enter environment [DEV2/QAT2/PPE2/PRD]"
read env
if test -z "$env" || test -z "$prevversion" || test -z "$newversion"; then
echo "Please enter the details and try again" >&2
exit 1
fi
case "$env" in
QAT2)
prevversion="$prevversion"_QAT2
newversion="$newversion"_QAT2
;;
PPE2)
prevversion="$prevversion"
newversion="$newversion"
;;
PRD)
prevversion="$prevversion"
newversion="$newversion"
;;
DEV2)
prevversion="$prevversion"_DEV2
newversion="$newversion"_DEV2
;;
esac
echo "previous version is $prevversion"
echo "new version is $newversion"
echo "enviornment is $env"

How to print a lines till a valid email id comes in shell?

#!/bin/sh
while read line
do
echo "Name: " "$line"
while []; do
#statements
done
done <input.txt
Use break when the input is validated.
Example:
while read -rp "Please enter email address " line ; do
if [[ "$line" =~ ^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]; then
echo OK
break
else
echo "Try again"
fi
done

Return to previous commands in bash script?

I'm trying to implement a prev option in my bash script to go back to the previous "menu", as well as a way for the script to ask for user input again if no variable is set for $name.
Heres my bash script:
#!/bin/bash
#Menu() {
for (( ; ; ))
do
beginORload=
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
read -p "?" beginORload
#}
#Begin() {
if [ "$beginORload" -eq "1" ]
then
clear
for (( ; ; ))
do
echo "Beginning. What is your name?"
read -p "?" name
#If "prev" specified, go back to #Menu()
if [ "$name" -eq "prev" ]
then
Menu
fi
#If nothing specified, return to name input
if [ -z ${name+x} ]
then
Begin
else
break
fi
echo "Hi $name !"
done
fi
done
In batch, I could simply do:
:menu
echo Choose option:
echo 1 - Begin
echo 2 - Load
[...]
:begin
[...]
if "%name%==prev" goto menu
if "%name%==" goto begin
the issue is I keep running into errors all over the place, and I can't figure out what to type to get it to work
im running Yosemite btw. Thankyou
Something like this is close to what you expect:
while [[ $answer -ne '3' ]];do
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
echo "3 - Exit"
read -p "Enter Answer [1-2-3]:" answer
case "$answer" in
1) while [[ "$nm" == '' ]];do read -p "What is your Name:" nm;done # Keep asking for a name if the name is empty == ''
if [[ $nm == "prev" ]];then nm=""; else echo "Hello $nm" && break; fi # break command breaks the while wrapper loop
;;
2) echo 'Load' ;;
3) echo 'exiting...' ;; # Number 3 causes while to quit.
*) echo "invalid selection - try again";; # Selection out of 1-2-3 , menu reloaded
esac # case closing
done # while closing
echo "Bye Bye!"
As a general idea you can wrap up your case selection in a while loop which will break under certain circumstances (i.e If Option 3 is selected or if a valid name is given (not blank - not prev)
PS1: In bash you compare integers with -eq , -ne, etc but you compare strings with == or !=
PS2: Check the above code online here

How do i jump back to the previous read if left empty

Default_Dir=/export/home/cwatts/test
Default_Log=DB.Audit
echo "Please, enter your Fullname [ENTER]:"
read fname
if [ -z "$fname" ]; then
echo "Please enter a value!"
exit 0
else
echo "Please, enter the Database name [ENTER]:"
read dbname
if [ -z "$dbname" ]; then
echo "Please enter a value!"
else
echo "Please, enter a brief Description [ENTER]:"
read desc
if [ -z "$desc" ]; then
echo "Please enter a value!"
fi
fi
fi
if [ ! -d $Default_Dir ]; then
echo "directory doesn't exit, it will be created"
mkdir $Default_Dir
fi
echo `date -u` $dbname $fname $desc >> $Default_Dir/$Default_Log
exit
You can do something like this:
while [ -z "${value-}" ]
do
echo "Please, enter your Fullname [ENTER]:"
read value
done
Expanding somewhat on l0b0's answer and refactoring for legibility and idiomatic expression:
nonempty () {
test -n "$1" && return 0
echo "Please enter a value" >&2
return 1
}
while true; do
read -p "Please, enter your Fullname [ENTER]: " fname
nonempty "$fname" || continue
read -p "Please, enter the Database name [ENTER]: " dbname
nonempty "$dbname" || continue
read -p "Please, enter a brief Description [ENTER]:" desc
nonempty "$desc" || continue
break
done
date -u +"%c $dbname $fname $desc" >> $Default_Dir/$Default_Log
(The hack to put the string you want to echo in the format string of date will break if any of the values could contain a percent sign.)
If you are okay with the slightly dubious practice of having a function define global variables for you, the code duplication can still be reduced significantly.
accept () {
read -p "$2 [ENTER]: " "$1"
test -n "${!1}" && return 0
echo "Please enter a value" >&2
return 1
}
while true; do
accept fname "Please, enter your Fullname" || continue
accept dbname "Please, enter the Database name" || continue
accept desc "Please, enter a brief Description" || continue
break
done
The indirect variable reference ${!var} is a Bashism, and not portable to other shells.

email shell script part 2

I'm creating a shell script that takes in user input and text's people using the mail function. I am looking to make it more advanced. Right now it just text's one person at a time, I want it to have the ability to text multiple people or even everyone with a user input of 'All'.
#!/bin/sh
# Prefix the numbers with something
number_Joe=8881235555
number_Bob=8881235556
echo "Who do you want to text?:(i.e. Joe, Bob, etc)"
read name
echo "What do you want to say?:"
read quote
# Remove any dangerous characters that the user enters
sanitized=$(printf "%s" "$name" | tr -cd 'a-zA-Z')
#Look up by evaluating e.g. "number=$number_Joe"
eval "number=\$number_$sanitized"
if [ "$number" ]
then
echo "texting $name ($number) with $quote"
printf "%s\n" "$quote" | mailx -s "Text Message via email" "$number#txt.att.net"
else
echo "Unknown user"
exit 1
fi
Also, is there a cleaner method of bringing in a external txt file that houses the numbers instead of the script?
(note: we still have bash <4, thus why I'm not using a associative array)
Here's a rewrite.
Should work fine in bash3.
#!/bin/bash
# Prefix the numbers with something
names=()
names+=(Joe); numberJoe=8881235555
names+=(Bob); numberBob=8881235556
domain=txt.att.example.com
usage () {
echo "usage: $(basename $0) names message ..."
echo "where: names is a comma-separated list of names (no spaces)"
echo
echo "example: $(basename $0) Jim,Fred hello lads, this is my message"
}
while getopts ":hl" opt; do
case $opt in
h) usage; exit ;;
l) IFS=,; echo "known names: ${names[#]}"; exit ;;
esac
done
shift $((OPTIND - 1))
if (( $# < 2 )); then
usage
exit
fi
IFS=, read -ra usernamelist <<<"$1"
shift
message="$*"
# validate names
namelist=()
for name in "${usernamelist[#]}"; do
if [[ " ${names[#]} " == *" $name "* ]]; then
namelist+=("$name")
else
echo "unknown name: $name" >&2
fi
done
if (( ${#namelist[#]} == 0 )); then
echo "no valid names given" >&2
exit 1
fi
# generate the recipient list
echo "texting '$message' to:"
recipients=()
for name in "${namelist[#]}"; do
numvar="number$name"
echo " $name -> ${!numvar}"
recipients+=( "${!numvar}#$domain" )
done
# send it
printf "%s\n" "$message" | mailx -s "Text Message via email" "$(IFS=,; echo "${recipients[*]}")"

Resources