How to Control Number of Parameters Entered into Function - linux

I am trying to make a simple menu-driven calculator script. I am trying to make it such that after selecting A (add) or B (subtract) from the menu, it'll call the function and display the corresponding message when:
The parameters entered when function called is greater than 3
No parameters are entered when the function is called
The operator entered when the function is called is neither "+" or "-"
Right now it is doing the parameter check when I call the script ./mycalc.sh
executing the script
Am not sure how to make it check parameters after the function is called?
#!/bin/bash
display() {
echo "Calculator Menu"
echo "Please select an option between add, subtract or exit"
echo "A. Add"
echo "B. Subtract"
echo "C. Exit"
}
#initialize choice n
choice=n
if [[ $# -ne 3 ]]
then echo " You have not entered 3 parameters"
exit 1
fi
if [ $# -eq 0 ]
then
echo " You have not entered any parameters, please input 3. "
fi
if [[ $2 != [+-] ]]
then
echo " Please enter an add or subtract operator."
exit 1
fi
add() {
echo " The sum of $one + $three equals $(( $one $op $three ))"
}
subtract () {
echo " The difference of $one - $three equals $(( $one $op $three )) "
}
while [ $choice != 'C' ]
do display
read choice
if [ $choice = 'A' ]
then
read -p "Please enter two operands and the operator '+': " one op three
add $one $op $three
elif [ $choice = 'B' ]
then
read -p " Please enter two operands and the operator '-': " one op three
subtract $one $op $three
elif [ $choice = 'C' ]
then
echo "Thank you for using this program. The program will now exit."
fi
done
sleep 3
exit 0

if [ $# > 3 ]
then
echo " You need to input 3 parameters. "
fi
Within [...], the > is simply redirection. You'll find an empty file named 3 in your current directory.
Since this is an error condition for your script, you'll want to exit:
if [[ $# -ne 3 ]]; then
echo "usage: $0 operand1 operator operand2" >&2
exit 1
fi
And to test the operator, there are many ways.
case, but it's a bit verbose
case $2 in
'+'|'-') : ;;
*) echo "Operator must be + or -" >&2
exit 1
;;
esac
Within [[...]] the == and != operators are pattern matching operators
if [[ $2 != [+-] ]]; then
echo "Operator must be + or -" >&2
exit 1
fi

Related

Bash - While Loop

I am having trouble with this while loop. Here is the error I am getting currently : [: : unary operator expected (on line 3)
Here is my code:
#!/bin/bash
while [ "$option" <= 3 ]; do
echo "1) View 'HelloWorld' Text";
echo "2) View 'MyName' Text";
echo "3) View 'HappyFall' Text";
echo "4) Exit\n";
read -p "Please choose your option using numbers 1-4: " option;
if [ "$option" == 1 ]
then
cat HelloWorld
elif [ "$option" == 2 ]
then
cat MyName
elif [ "$option" == 3 ]
then
cat HappyFall
else
echo "Exiting...";
fi
done
<= is not a valid comparison in bash scripting, but -le (less than or equal) is.
There are two different types of comparison in scripting: those for strings, and those for numbers.
Stings typically use == or != for equal or not equal.
Integers, however, use:
-eq equal
-ne not equal
-lt less than
-le less than or equal
-gt greater than
-ge greater than or equal
Here's a more comprehensive list:
http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Conditional_Blocks_.28if.2C_test_and_.5B.5B.29
Error aside, this is a good use case for the select command:
options=(
"View 'HelloWorld' Text"
"View 'MyName' Text"
"View 'HappyFall' Text"
"Exit"
)
select option in "${options[#]}"; do
case $REPLY in
1) cat HelloWorld ;;
2) cat MyName ;;
3) cat HappyFall ;;
*) break ;;
esac
done

How can I create a menu in a shell script?

I want to create a select menu in it, like this:
echo "Choose your option:"
1) Factorial Calculation
2) Addition Calculator
3) Quit
And I have some shell scripts;
Factorial
./fact.sh
#!/bin/bash
fact=1
#taking input from user
echo -e "enter a number"
read n
#if enter value less than 0
if [ $n -le 0 ] ; then
echo "invalid number"
exit
fi
#factorial logic
if [ $n -gt 0 ] ; then
for((i=$n;i>=1;i--))
do
fact=`expr $fact \* $i`
done
fi
echo "The factorial of $n is $fact"
Addition
./add.sh
#!/bin/bash
#function to add two numbers
add()
{
x=$1
y=$2
echo -e "Number entered by u are: $x and $y"
echo "sum of $1 and $2 is `expr $x + $y` "
}
# main script
echo "enter first number"
read first
echo "enter second number"
read sec
#calling function
add $first $sec
echo "end of the script"
I have to create a menu, how should I proceed?
You can use select.
For your example:
select option in Factorial Addition Quit; do
case "$option" in
"Factorial")
echo "Factorial"
break ;;
"Addition")
echo "Addition"
break ;;
"Quit") exit ;;
esac
done

Parameters in Linux shell script

I am trying to create a script file in Linux that acts as a basic calculator. It needs to pass 3 parameters or no parameters.
If it has 3 parameters, it should be able to execute like this.
./mycalc 1 + 2
the sum of 1 plus 2 equals 3
But if it does not have any parameters a menu should display asking for subtraction, addition, or exit.
How would this layout look? I keep trying but whenever I run it it gives me errors saying I need to enter the parameters and then after the error the menu displays.
op="$2"
if [ $op == "+" ]
then
sum=$(expr $1 + $3)
echo "The sum of $1 plus $3 equals $sum"
elif [ $op == "-" ]
then
diff=$(expr $1 - $3)
echo "The sum of $1 minus $3 equals $diff"
else
while [ $ch != "X" ] || [ $ch != "x" ]
do
read -p "C) Calculation
X) Exit" ch
Here's a "cute" answer. I'll give you some feedback on your code later.
#!/bin/bash
case $2 in
+|-) :;;
*) echo "unknown operator: $2"; exit 1;;
esac
declare -A ops=(
["-"]=minus
["+"]=plus
)
printf "%d %s %d equals %d\n" "$1" "${ops["$2"]}" "$3" "$(bc <<< "$*")"
Here's a rewrite, hopefully demonstrating a few useful techniques and good practices
#!/bin/bash
user_args () {
case $2 in
+) echo "The sum of $1 plus $3 equals $(( $1 + $3 ))" ;;
-) echo "The sum of $1 minus $3 equals $(( $1 - $3 ))" ;;
*) echo "I don't know what to do with operator '$2'" ;;
esac
}
interactive () {
PS3="Select an operator: "
select choice in plus minus exit; do
case $choice in
plus) operator="+"; break ;;
minus) operator="-"; break ;;
exit) exit;;
esac
done
read -p "First value: " first
read -p "Second value: " second
echo "The sum of $first $choice $second equals $(( $first $operator $second ))"
}
if (( $# == 3 )); then
user_args "$#"
else
interactive
fi
use of functions for modularity
case statement for easily expanded branching
select statement to generate the menu and enforce valid input
bash's built-in arithmetic expressions
passing arguments with "$#"
quoting variables everywhere the need to be quoted
Command line parameters are referenced as $1, $2, $3...
($1 for first arg, $2 for second ...)
you can test if parameters are not null with :
if [ -z "$1" ]
then
echo "No argument supplied"
fi

Shell script to take multiple user input in single file

A shell script should take multiple condition in single line input and it should take one end of input character to perform next operation. ie.
#!/bin/bash
#Functions are defined here 1 2 3 4 5
echo "choice"
echo
echo "[1] one"
echo "[2] two"
echo "[3] three"
echo "[4] four"
echo "[5] five"
echo
read -p "Enter choice: " ch
if [ "$ch" = "1" ]; then
function_1
else
if [ "$ch" = "2" ]; then
function_2
else
if [ "$ch" = "3" ]; then
function_3
else
if [ "$ch" = "4" ]; then
function_4
else
if [ "$ch" = "5" ]; then
function_5
fi
fi
fi
fi
fi
now say end of input taking denoted by 'e' hence if I execute the .sh file and in "Enter choice"
$Enter choice: 1 3 5 e
it should execute 1 3 and 5th function one by one
how to do that?
You can iterate over all the choices until you find the 'end of input':
read -p "Enter choice: " ch
for choice in $ch; do
[ "$choice" == 'e' ] && break
eval function_$choice
done
NOTE: eval will assemble a command from the arguments and then execute it through the shell
You should iterate over your string ch until "e" appears:
#!/bin/bash
#Functions are defined here 1 2 3 4 5
echo "choice"
echo
echo "[1] one"
echo "[2] two"
echo "[3] three"
echo "[4] four"
echo "[5] five"
echo
read -p "Enter choice: " ch
for i in ${ch}
do
if [ "$i" == "1" ]; then
function_1
else if [ "$i" == "2" ]; then
function_2
else if [ "$i" == "3" ]; then
function_3
else if [ "$i" == "4" ]; then
function_4
else if [ "$i" == "5" ]; then
function_5
else if [ "$i" == "e" ]; then
break
fi
fi
fi
fi
fi
fi
but the answer of mxlian is "cleaner". i just corrent your code..
It would be better if you made each input parameter an option and used getopts ie
myProg.sh -a aArg -b bArg -c cArg
Inside myProg.sh:
while getopts "a:b:c" option
do
case $option in
a) function_1;;
b) function_2;;
c) function_3;;
*) exitFunc "Incorrect argument";; # You need to write exitFunc()
esac
done
This way you can have a missing option ie only option a and c (no b). If you do it your way and one parameter is missing (or null) say paramater 3 then parameter 4 becomes parameter 3 etc.

unexpected End of File error in if else statement

I keep getting unexpected End of file error while running a if else statement
#! /bin/bash
echo -e "1: Proband\n 2: mincount\n Enter an option:"
read promin
echo $promin
if ($promin == 1) then
echo -e "Enter the proband file name\n"
read proband_file
echo "$proband_file"
endif
if ($promin == 2) then
echo -e "enter the min count number\n"
read mincount
echo "$mincount mincount"
endif
I tried fi instead of elseif too. But i still get the same error. Can someone help me fix that?
This is how you write an if-statement in bash:
if - then - fi
if [ conditional expression ]
then
statement1
statement2
fi
if - then - else - fi
If [ conditional expression ]
then
statement1
statement2
else
statement3
statement4
fi
if - then - elif - else - fi
If [ conditional expression1 ]
then
statement1
statement2
elif [ conditional expression2 ]
then
statement3
statement4
else
statement5
fi
Example of a conditional expression:
#!/bin/bash
count=100
if [ $count -eq 100 ]
then
echo "Count is 100"
fi
IMPROVED
The if is syntax is not correct. In the if there should be a program (bash internal or external) run, which returns an exit code. If it is 0 then if is true, otherwise it is false. You can use grep or any other utility, like test or /usr/bin/[. But bash has a built-in test and [.
So [ "$var" -eq 1 ] returns 0 if $var equals 1, or return 1 if $var not equals 1.
In your case I would suggest to use case instead of if-then-elif-else-fi notation.
case $x in
1) something;;
2) other;;
*) echo "Error"; exit 1;;
easc
Or even use select. Example:
#!/bin/bash
PS3="Enter an option: "
select promin in "Proband" "mincount";do [ -n "$promin" ] && break; done
echo $promin
case "$promin" in
Proband) read -p "Enter the proband file name: " proband_file; echo "$proband_file";;
mincount) read -p "Enter the min count number: " mincount; echo "$mincount mincount";;
*) echo Error; exit 1;;
esac
This will print the "Enter an option: " prompt and wait until a proper answer is presented (1 or 2 or ^D - to finish the input).
1) Proband
2) mincount
Enter an option: _
Then it checks the answer in the case part. Meanwhile $promin contains the string, $REPLY contains the entered answer. It also can be used in case.
I just changed your code and I think it works now.
I think the problem is you should fi instead of endif...
#!/bin/sh
echo "1: Proband\n2: mincount\nEnter an option:"
read promin
echo $promin
if [ $promin -eq "1" ]
then
echo "Enter the proband file name\n"
read proband_file
echo "$proband_file"
elif [ $promin -eq "2" ]
then
echo "enter the min count number\n"
read mincount
echo "$mincount mincount"
fi
#! /bin/bash
echo -e "1: Proband\n2: mincount\nEnter an option:"
read promin
echo $promin
if (($promin == 1)); then
echo -e "Enter the proband file name\n"
read proband_file
echo "$proband_file"
elif (($promin == 2)); then
echo -e "Enter the min count number\n"
read mincount
echo "$mincount mincount"
fi
I don't know if you need an if-else statement or two if statemnts. The above has an if-else.
If you need two if statements, then insert a line of code below the "echo "$proband_file"" line with the text:
fi
Then replace the line "elif (($promin == 2)); then" with the following code:
if (($promin == 2)); then

Resources