check if the argument is a number inside the shell script [duplicate] - shell

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I test if a variable is a number in bash?
I try writing the fibonacci sequence by shell scripting for example if user entered 5 after the script name in the command line the script needs to print out the 5 fibonacci numbers from the beginning which are:
0 1 1 2 3
I have completed the script but I need to check the user input if it is positive number that I have a problem in this part.
in the command line the user should call the script and then enter a positive number
./script number
and this is my code:
#!/bin/sh
[ $# -ne 1 ] && { echo "enter a number please" ; exit 1 ; }
[ ! echo $1 | egrep -q '^[0-9]+$' && $1 -lt 0 ] && { echo "negative" ; exit 1 ; }
f0=0
f1=1
counter=2
if [ $1 -eq 0 ] ; then
echo -n "0"
elif [ $1 -ge 1 ] ; then
echo -n "0 1"
fi
while [ $counter -le $1 ] && [ $1 -gt 1 ] ; do
echo -n "$fn "
fn=`expr $f0 + $f1`
f0=$f1
f1=$fn
counter=`expr $counter + 1`
done
echo ""

if [ $1 -ge 0 2>/dev/null ] ; then
it works for positive numbers equal or greater than 0

Take a look at this:
http://www.bashguru.com/2010/12/how-to-validate-integer-input-using.html
Apparently someone wrote multiple shell scripts to do exactly that.

Related

How to fix count that doesn't work in while loop

I have been trying to resolve an issue where my loop's count should decrease, however nothing is working. I need to create a while loop that will read over a given amount of times. For instance, if I enter in "files.txt -a 3" in the terminal, I need my loop to repeat "Enter in a string: " 3 times. With my code below, I am only able to get it to loop once. I am not to sure where to put the counter and I can say that I have put it everywhere. Inside the if statement, in inside of the for loop, and inside the while loop but none seem to work. The number that the user will put is held in the $count variable.
#!/bin/bash
if ["$1" = "-a" ]
then
read in user String and save into file
fi
while [ "$count" > 0 ]
do
for i in $count
do
if [ "-a" ]
then
read -p "Enter in a string: " userSTR
echo userSTR >> files.txt
count=$(($count - 1))
fi
done
done
For conditional expression you need to use [[ expression ]], e.g. this will loop four times:
count=4
while [[ $count > 0 ]] ; do
echo "$count"
count=$(( $count - 1 ))
done
To fetch the count from the command-line argument, you could replace the assignment count=4 above with the following, parsing the command-line arguments:
if [ $# -lt 2 ] ; then
echo "Usage: $0 -a [count]"
exit 1
fi
if [ "$1" = "-a" ] ; then
shift
count=$1
fi

script8.sh: line 9: [: missing `]' [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 3 years ago.
I'm trying to do test automation with a bash script using if then else statements but I'm running into a few errors. For one, when I try to execute it I'm doing something wrong with the variable assignment with j and k, because it tells me that the command j and the command k aren't found when I try to execute. How do you correctly create variables?
The most confusing thing though is when I try to execute the script I get an error telling me I have an unexpected token near fi, and then it just says 'fi'. What am I doing wrong here?
#!/bin/bash
j = 0
k = 0
echo Test1:
echo -ne "0\nIn\nUG\n" | /u/cgi_web/Tuition/cost
echo Test2:
echo -ne "0\nOut\nUG\n" | /u/cgi_web/Tuition/cost
echo Test3:
echo -ne "0\nIn\nGR\n" | /u/cgi_web/Tuition/cost
echo Test4:
echo -ne "0\nOut\nGR\n" | /u/cgi_web/Tuition/cost
for i in {1..17}
do
echo Test$((i+4)):
if[ "$j" -eq 0 ] && [ "$k" -eq 0 ] then
$j = 1
echo -ne "$i\nIn\nUG\n" | /u/cgi_web/Tuition/cost
elif[ "$j" -eq 1 ] && [ "$k" -eq 0 ] then
$k = 1
echo -ne "$i\nIn\nGR\n" | /u/cgi_web/Tuition/cost
elif[ "$j" -eq 1 ] && [ "$k" -eq 1 ] then
$j = 0
echo -ne "$i\nOut\nUG\n" | /u/cgi_web/Tuition/cost
elif[ "$j" -eq 0 ] && [ "$k" -eq 1 ] then
$k = 0
echo -ne "$i\nOut\nGR\n" | /u/cgi_web/Tuition/cost
fi
done
EDIT: I figure out the variable issue with j and k, I had to remove the spaces in the statement.
Bash if statements require a semi-colon before the then:
if [ condition ] || [ condition ]; then
# code
elif [ condition ] && [ condition ]; then
# code
fi
For example.
To help anyone who might look at this for help in the future, I figured I'd answer my own question with all the syntax errors I found from my own testing and with the helpful responses of others.
To start the variable assignment:
j = 0
you can't have spaces in between, so it would be:
j=0
Also if statements need a space between if and the bracket and need a semicolon after the last bracket before then. Therefore my incorrect if statement
if[ "$j" -eq 0 ] && [ "$k" -eq 0 ] then
becomes
if [ "$j" -eq 0 ] && [ "$k" -eq 0 ]; then
or instead of a semicolon you can have a new line between the bracket, so it would become
if [ "$j" -eq 0 ] && [ "$k" -eq 0 ]
then

Why is my bash script creating files without telling it to?

I am running the following script, which has a function intended to tell me whether one date is before another, as seen at the very bottom of the script.
Now, the script has a few bugs. But one of them in particular is strange. The script creates files named by the dates that are inputted by the last argument.
It creates files called "09", "12", and "2015". Why are these files created? Here's the function. You'll notice the last few lines which call the function with inputs
function compare_two {
if [ $1 < $2 ];
then
return 2
elif [ $1 > $2 ];
then
return 3
else
return 4
fi
}
function compare_dates {
# two input arguments:
# e.g. 2015-09-17 2011-9-18
date1=$1
date2=$2
IFS="-"
test=( $date1 )
Y1=${test[0]}
M1=${test[1]}
D1=${test[2]}
test=( $date2 )
Y2=${test[0]}
M2=${test[1]}
D2=${test[2]}
compare_two $Y1 $Y2
if [ $? == 2 ];
then
echo "returning 2"
return 2
elif [ $? == 3 ];
then
return 3
else
compare_two $M1 $M2;
if [ $? == 2 ];
then
echo "returning 2"
return 2
elif [ $? == 3 ];
then
return 3
else
compare_two $D1 $D2;
if [ $? == 2 ];
then
echo $?
echo "return 2"
return 2
elif [ $? == 3 ];
then
echo "returning 3"
return 3
else
return 4
fi
fi
fi
}
compare_dates 2015-09-17 2015-09-12
echo $?
the result doesn't throw an error, but rather outputs
returning 2
2
The result is incorrect, I'm aware. But I'll fix that later. What is creating these files and how do I stop it? Thanks.
the lower and greater sign are interpreted as redirections.
type man test and find out the right syntax
Your problem is with the [ $1 < $2 ], the < is being understood as a redirection character.
The solution is to use any of this alternatives:
[ $1 \< $2 ]
[ $1 -lt $2 ]
(( $1 < $2 )) # works in bash.
The [[ $1 < $2 ]] is NOT an integer compare, but (from the manual):
« the < and > operators sort lexicographically using the current locale »
I'll recommend to use the (( $1 < $2 )) option.
to avoid a problem that some numbers (the ones that start with a zero) like 08 cause a problem when compared in an arithmetic expansion, use:
(( 10#$1 < 10#$2 ))
(( 10#$1 > 10#$2 ))
to force a base 10 for the numbers.
However, if possible, using GNU date is a lot easier IMhO (it transform Year/Month/Day into one single number to compare: seconds since epoch):
a=$(date -d '2015-09-17' '+%s');
b=$(date -d '2015-09-12' '+%s');
compare_two "$a" "$b"

How to use the exit status from a function within my script

I have a script and within it I call a function. How can I use the exit status from the function to print a message, without incorporating the message inside the function?
I am supposed to write a script which has:
Your script should contain a function increasingNos that uses three parameters. All three parameters should be integers. The function is a "success" (with exit status 0) if there are exactly three parameters and they are numbers in increasing order. The function should have an exit status of 1 if there are three parameters but they are not in increasing order. The function should should have an exit status of 2 if there are fewer or more than 3 parameters.
and...
you should print an appropriate message to the standard output after calling increasingNos with parameters 17 5 23 to say whether or not there were three parameters and whether or not they were numbers in increasing order. Use an if conditional and the exit status on your function call to do this. This if conditional may not be in the function increasingNos.
This is what I have come up; whenever I run the script, it exits when the function call hits an exit status. How can I execute the rest of the script?
increasingNos(){
if [ $# -ne 3 ];then
exit 2
fi
if [ $1 -ge $2 ] || [ $2 -ge $3 ];then
exit 1
else
exit 0
fi
}
increasingNos 17 5 23
if [ $? -eq 2 ];then
echo "You did not supply exactly 3 integer parameters!"
fi
if [ $? -eq 1 ];then
echo "Your parameters were not input in increasing order!"
fi
if [ $? -eq 0 ];then
echo "Congrats, you supplied 3 integers in increasing order!"
fi
Use return instead of exit and save the value of $? in a variable, because it will change after the first test.
This works:
increasingNos(){
if [ $# -ne 3 ];then
return 2
fi
if [ $1 -ge $2 ] || [ $2 -ge $3 ];then
return 1
else
return 0
fi
}
increasingNos 17 5 23
stat=$?
if [ $stat -eq 2 ];then
echo "You did not supply exactly 3 integer parameters!"
fi
if [ $stat -eq 1 ];then
echo "Your parameters were not input in increasing order!"
fi
if [ $stat -eq 0 ];then
echo "Congrats, you supplied 3 integers in increasing order!"
fi
You need to use return rather than exit in your functions.

Shell Script Too Many Arguments for if condition

My current script does the following;
It takes integer as a command line argument and starts from 1 to N , it checks whether the numbers are divisible by 3, 5 or both of them. It simply prints out Uc for 3, Bes for 5 and UcBes for 3,5. If the command line argument is empty, it does the same operation but the loop goes to 1 to 20.
I am having this error "Too many arguments at line 11,15 and 19".
Here is the code:
#!/bin/bash
if [ ! -z $1 ]; then
for i in `seq 1 $1`
do
if [ [$i % 3] -eq 0 ]; then
echo "Uc"
elif [ i % 5 -eq 0 ]; then
echo "Bes"
elif [ i % 3 -eq 0 ] && [ i % 5 -eq 0 ]
then
echo "UcBes"
else
echo "$i"
fi
done
elif [ -z $1 ]
then
for i in {1..20}
do
if [ i % 3 -eq 0 ]
then
echo "Uc"
elif [ i % 5 -eq 0 ]
then
echo "Bes"
elif [ i % 3 -eq 0 ] && [ i % 5 -eq 0 ]
then
echo "UcBes"
else
echo "$i"
fi
done
else
echo "heheheh"
fi
Note that [ is actually synonym for the test builtin in shell (try which [ in your terminal), and not a conditional syntax like other languages, so you cannot do:
if [ [$i % 3] -eq 0 ]; then
Moreover, always make sure that there is at least one space between [, ], and the variables that comprise the logical condition check in between them.
The syntax for evaluating an expression such as modulo is enclosure by $((...)), and the variable names inside need not be prefixed by $:
remainder=$((i % 3))
if [ $remainder -eq 0 ]; then
You should probably use something like :
if [ $(($i % 3)) -eq 0 ]
instead of
if [ $i % 3 -eq 0 ]
if [ [$i % 3] -eq 0 ]
Your script could be greatly simplified. For example:
#!/bin/sh
n=0
while test $(( ++n )) -le ${1:-20}; do
t=$n
expr $n % 3 > /dev/null || { printf Uc; t=; }
expr $n % 5 > /dev/null || { printf Bes; t=; }
echo $t
done
gives slightly different error messages if the argument is not an integer, but otherwise behaves the same.

Resources