line 14: [: 55.5: integer expression expected --shell error - bash

I'm getting error for line 8,11,14,17 .
the program is
#!/bin/sh
read a
b=$(grep -i $a TeamScore.txt| awk 'BEGIN{FS =" "}{print ($2+$4)/2}')
echo "the avg is $b"
if [ "$b" -ge 80] #line8
then
echo "1st class "
elif [ "$b" -lt 80 ] || [ "$b" -ge 70 ] #line11
then
echo "2nd class"
elif [ "$b" -lt 70 ] || [ "$b" -ge 60 ] #line14
then
echo "3rd class"
elif [ "$b" -lt 60 ] #line17
then
echo "fail"
else
echo "code not working"
fi
I'm new to unix and shell scripting and i would like to whats wrong and how can i fix it.the TeamScore.txt contains a table of names and their score(for 2 exams).

The problem is that the test command only understands integers, but you're setting b to 55.5, which contains a fraction. Change the awk command to round it down.
b=$(grep -i $a TeamScore.txt| awk 'BEGIN{FS =" "}{print int(($2+$4)/2)}')
You also need a space before ] on line #8.

Line 8: add an extra space:
if [ "$b" -ge 80 SPACE_HERE_REQUIRED ]
Line11, line14 and line17: number operators can't be compared with strings, so use $b instead of "$b", so, for example, use this
if [ $b -ge 80 ]
instead of:
if [ "$b" -ge 80 ]

Related

-eq unary operator expected

I have this code here.
But I get the error:
./concatconvert: line 9: [: -eq: unary operator expected
./concatconvert: line 18: [: -eq: unary operator expected
This is my code:
#!/bin/bash
param=$#
if [ $# -le 2 ]
then
echo "Usage: concatconvert [-u|-1] FILE ...
Description: concatenates FILE(s) to standard output separating them with divider -----. Optional first argument -u or -l converts contents to uppercase or lowercase,$
fi
if [ $1 -eq "-u" ]
then
while [ $param -ge 1 ]
do
./concat | awk '{print toupper($0)}'
param=$(( param-1 ))
shift
done
fi
if [ $1 -eq "-l" ]
then
while [ $param -ge 1 ]
do
./concat | awk '{print tolower($0)}'
param=$(( param-1 ))
shift
done
fi
Why am I getting this error? I thought that -eq is a unary operator?
You have missed few things eg--> " for echo command was NOT closed. Then in if condition since you are comparing a string so change it to if [[ "$1" = "-u" ]] so following could be the script(I haven't tested it since no samples were there).
#!/bin/bash
param=$#
if [ $# -le 2 ]
then
echo "Usage: concatconvert [-u|-1] FILE ...
Description: concatenates FILE(s) to standard output separating them with divider -----. Optional first argument -u or -l converts contents to uppercase or lowercase,$"
fi
if [[ "$1" = "-u" ]]
then
while [ $param -ge 1 ]
do
./concat | awk '{print toupper($0)}'
param=$(( param-1 ))
shift
done
fi
if [[ $1 -eq -l ]]
then
while [ $param -ge 1 ]
do
./concat | awk '{print tolower($0)}'
param=$(( param-1 ))
shift
done
fi

Validating number of arguments

I apologize for the beginners question ahead of time but I cannot get this chunk of code to work properly. I was asked to make a basic program which asks the user for 3 numbers and then checks which is the highest value and prints the results, as well as makes sure there are three numbers put in. It can determine which is his highest and im getting it to output results properly but I cant seem to figure out how to get it to validate that there are three numbers put in.
I have done research and even pulled some code from the teachers example about how to check the number of arguments but I still cant get it to work.
#!/bin/bash
echo "Please enter three numbers:"
read a b c
if [ $# -ne 3 ]
then
echo "You need three numbers"
exit -1
fi
if [ $a -gt $b -a $a -gt $c ]
then
LARGEST=$a
elif [ $b -gt $a -a $b -gt $c ]
then
LARGEST=$b
elif [ $c -gt $a -a $c -gt $b ]
then
LARGEST=$c
elif [ $a -eq $b -a $a -eq $c -a $b -eq $c -eq $b ]
then
LARGEST="All three values are equal."
fi
echo "The largest values is $LARGEST"
When I enter three numbers (7 8 9) I expect to get back:
"The largest value is 9"
however I get this instead:
./values.sh: line 6 [0: command not found
The largest value is 9
Am i missing something blatantly obvious here? I know i need an operator to make my original if statement work but am i using the wrong one?
The [ -z "$c" ] test solves it for the code you posted.
Working code:
#!/bin/bash
echo "Please enter three numbers:"
read a b c d
if [ -z "$c" ]
then
echo "You need three numbers"
exit -1
fi
if [ -n "$d" ]
then
echo "enter only three numbers"
exit -1
fi
if [ $a -gt $b -a $a -gt $c ]
then
LARGEST=$a
elif [ $b -gt $a -a $b -gt $c ]
then
LARGEST=$b
elif [ $c -gt $a -a $c -gt $b ]
then
LARGEST=$c
elif [ $a -eq $b -a $a -eq $c -a $b -eq $c -eq $b ]
then
LARGEST="All three values are equal."
fi
echo "The largest values is $LARGEST"
Output:
$ ./t.sh
Please enter three numbers:
7 8
You need three numbers
$ ./t.sh
Please enter three numbers:
7 8 9
The largest values is 9

IP address calculator script

I need to write a Bash script that converts IP address from CIDR format to quad-style.
I must enter the IP address in the following style:
10.10.10.10/24
If I entered it in this style:
10.10.10.10 255.255.255.0
an error message should appear.
I tried this script:
#!/bin/bash
echo "enter you ip"
read ip
case $ip in
*.*.*.*/*)
b=`echo $ip | cut -d/ -f1`
a=`echo $ip | cut -d/ -f2`
if [ $a -eq 24 ];then
echo "$b 255.255.255.0"
elif [ $a -eq 25 ];then
echo "$b 255.255.255.128"
elif [ $a -eq 26 ];then
echo "$b 255.255.255.192"
elif [ $a -eq 27 ];then
echo "$b 255.255.255.224"
elif [ $a -eq 28 ];then
echo "$b 255.255.255.240"
elif [ $a -eq 29 ];then
echo "$b 255.255.255.248"
elif [ $a -eq 30 ];then
echo "$b 255.255.255.252"
elif [ $a -eq 31 ];then
echo "$b 255.255.255.254"
elif [ $a -eq 32 ];then
echo "$b 255.255.255.255"
fi
case $ip in
*.*.*.* *.*.*.*)
echo "enter a valid address"
esac
but I get an error
./ipcalculater2.sh: line 32: syntax error near unexpected token `...'
./ipcalculater2.sh: line 32: ` ... ...)'
What is wrong with my script?
Here's an example of four ways one might convert from CIDR to netmask notation in bash.
#!/usr/bin/env bash
if [[ "$1" != *.*.*.*/* ]]; then
echo "Usage: ${0##*/} ip.ad.dr.ess/bits" >&2
exit 1
fi
# separate our input into network and mask using IFS
IFS=/ read network bits <<<"$1"
# build a temporary variable $s that we'll use to build $bitmask
# for the first three variants...
read zeros <<< $(printf '%032s' 0)
s=${zeros//0/1}${zeros}
# convert the mask into a 32-digit binary number
bitmask=${s:$((32-bits)):32}
# Four different methods for generating the netmask...
# The first two use `bc` and `dc`. One is likely installed on your system.
read mask1 <<<$( dc -e "2i $(fold -w8 <<<"$bitmask " | paste -sdp -)" | paste -sd. - )
read mask2 <<<$( fold -w8 <<<"$bitmask" | paste - | bc -e 'ibase=2' | paste -sd. - )
# And if dc and bc are unavailable, or you prefer not to spawn subshells, or
# risk missed dependencies, you can do this in pure bash with a few more lines.
unset mask3
for ((i=0;i<4;i++)); do
mask3+="${mask3:+.}$((2#${bitmask:$((8*i)):8}))"
done
# And finally, instead of a loop, you can do the same thing with fancy math:
# This variant avoides the need for $bitmask, set above.
mask4="$(( 2**32 - (1 << (32-$bits)) ))"
mask4=$(( mask4/2**24 )).$(( mask4/2**16 %256 )).$(( mask4/2**8 % 256 )).$(( mask4 % 256 ))
# Print the results, obviously.
echo "network=$network"
echo "netlength=$bits"
echo "netmask via 'dc': $mask1"
echo "netmask via 'bc': $mask2"
echo "netmask via loop: $mask3"
echo "netmask via math: $mask4"
I've included code that works in each of dc and bc, since I can't predict which calculator will be available on your system. These calculators are used for base conversion. If you don't mind your script being a little longer, you can avoid spawning external tools (like fold and paste and the calculator) using the method that generates $netmask3.
Note that in the third case, this usage of bc depends on availability of a -e option which exists in *BSD. Use another variant if you're using GNU bc (i.e. you're in Linux.)
You can of course adjust the output so that it meets your needs, as well as trim the parts of the script you're not using.
Please check for this corrections:
#!/bin/bash
echo "enter you ip"
read ip
case $ip in
*.*.*.*/*)
b=`echo $ip | cut -d/ -f1`
a=`echo $ip | cut -d/ -f2`
if [ $a -eq 24 ];then
echo "$b 255.255.255.0"
elif [ $a -eq 25 ];then
echo "$b 255.255.255.128"
elif [ $a -eq 26 ];then
echo "$b 255.255.255.192"
elif [ $a -eq 27 ];then
echo "$b 255.255.255.224"
elif [ $a -eq 28 ];then
echo "$b 255.255.255.240"
elif [ $a -eq 29 ];then
echo "$b 255.255.255.248"
elif [ $a -eq 30 ];then
echo "$b 255.255.255.252"
elif [ $a -eq 31 ];then
echo "$b 255.255.255.254"
elif [ $a -eq 32 ];then
echo "$b 255.255.255.255"
fi
;;
*.*.*.*\ *.*.*.*)
echo "enter a valid address"
;;
esac

shell program does not show the value of the character given as input?

I am inputting a single character from the user and trying to print the ascii value of the character if it's value is >=97 and <=121
This is my code and it does not work.
echo "Enter a character"
read n
if ["'${n}" -ge 97 and "'${n}" -le 121]
then
print "%d","'$n"
fi
Error:
ascii.sh: 3: ascii.sh: ['a: not found
[ is a command in shell, aka test command.
You need spaces around [ and ].
Moreover, in order to compare integers you need to use < and >.
EDIT: In order to fix, you could say:
read n
asc=$(printf "%d" "'$n")
[[ "$asc" > 97 ]] && [[ "$asc" < 122 ]] && echo $asc
If you're using sh, you could change the last line to:
[ "$asc" -gt 97 ] && [ "$asc" -le 121 ] && echo $asc
Something like this will make it:
#!/bin/sh
min=97
max=121
echo "Enter a character"
read n
value=$(printf "%d" "'$n")
printf "The ASCII character of %s is %d.\n" "$n" "$value"
if [ "${value}" -le $min ] && [ "${value}" -le $max ]
then
printf "%d not in the range.\n" "$value"
else
printf "%d in the range.\n" "$value"
fi
Things that I changed:
- printf instead of print.
- ["'${n}" -ge 97 and "'${n}" -le 121] condition needed to be splited in two blocks:
if [ "${n}" -le 97 ] && [ "${n}" -le 121 ]

Integer expression expected error in shell script

I'm a newbie to shell scripts so I have a question. What Im doing wrong in this code?
#!/bin/bash
echo " Write in your age: "
read age
if [ "$age" -le "7"] -o [ "$age" -ge " 65" ]
then
echo " You can walk in for free "
elif [ "$age" -gt "7"] -a [ "$age" -lt "65"]
then
echo " You have to pay for ticket "
fi
When I'm trying to open this script it asks me for my age and then it says
./bilet.sh: line 6: [: 7]: integer expression expected
./bilet.sh: line 9: [: missing `]'
I don't have any idea what I'm doing wrong. If someone could tell me how to fix it I would be thankful, sorry for my poor English I hope you guys can understand me.
You can use this syntax:
#!/bin/bash
echo " Write in your age: "
read age
if [[ "$age" -le 7 || "$age" -ge 65 ]] ; then
echo " You can walk in for free "
elif [[ "$age" -gt 7 && "$age" -lt 65 ]] ; then
echo " You have to pay for ticket "
fi
If you are using -o (or -a), it needs to be inside the brackets of the test command:
if [ "$age" -le "7" -o "$age" -ge " 65" ]
However, their use is deprecated, and you should use separate test commands joined by || (or &&) instead:
if [ "$age" -le "7" ] || [ "$age" -ge " 65" ]
Make sure the closing brackets are preceded with whitespace, as they are technically arguments to [, not simply syntax.
In bash and some other shells, you can use the superior [[ expression as shown in kamituel's answer. The above will work in any POSIX-compliant shell.
This error can also happen if the variable you are comparing has hidden characters that are not numbers/digits.
For example, if you are retrieving an integer from a third-party script, you must ensure that the returned string does not contain hidden characters, like "\n" or "\r".
For example:
#!/bin/bash
# Simulate an invalid number string returned
# from a script, which is "1234\n"
a='1234
'
if [ "$a" -gt 1233 ] ; then
echo "number is bigger"
else
echo "number is smaller"
fi
This will result in a script error : integer expression expected because $a contains a non-digit newline character "\n". You have to remove this character using the instructions here: How to remove carriage return from a string in Bash
So use something like this:
#!/bin/bash
# Simulate an invalid number string returned
# from a script, which is "1234\n"
a='1234
'
# Remove all new line, carriage return, tab characters
# from the string, to allow integer comparison
a="${a//[$'\t\r\n ']}"
if [ "$a" -gt 1233 ] ; then
echo "number is bigger"
else
echo "number is smaller"
fi
You can also use set -xv to debug your bash script and reveal these hidden characters. See https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-error-integer-expression-expected-934465/
./bilet.sh: line 6: [: 7]: integer expression expected
Be careful with " "
./bilet.sh: line 9: [: missing `]'
This is because you need to have space between brackets like:
if [ "$age" -le 7 ] -o [ "$age" -ge 65 ]
look: added space, and no " "
Try this:
If [ $a -lt 4 ] || [ $a -gt 64 ] ; then \n
Something something \n
elif [ $a -gt 4 ] || [ $a -lt 64 ] ; then \n
Something something \n
else \n
Yes it works for me :) \n
If you are just comparing numbers, I think there's no need to change syntax, just correct those lines, lines 6 and 9 brackets.
Line 6 before: if [ "$age" -le "7"] -o [ "$age" -ge " 65" ]
After: if [ "$age" -le "7" -o "$age" -ge "65" ]
Line 9 before: elif [ "$age" -gt "7"] -a [ "$age" -lt "65"]
After: elif [ "$age" -gt "7" -a "$age" -lt "65" ]

Resources