How to say less than but no equal to in bash? - bash

I'm getting an error with this, I did my research but found nothing.
if [ $value -lt 3 -ne 1 ]; then
execute code
fi
line 6: [: syntax error: -ne unexpected

One way to make this work is
if [ "${value}" -lt 3 ] && [ "${value}" -ne 1 ]; then
echo "Hello"
fi

I like to switch to arithmetic expressions using (( when I need tests like these:
declare -a values=(1 2 3)
for value in "${values[#]}"; do
if (( value != 1 && value < 3 )); then
echo "execute code for $value"
fi
done
The above outputs:
execute code for 2

use (( )) brackets for arithmetic operations and [[ ]] for strings comparison
$ is redundant in round brackets so (( $a == 1 )) is the same as (( a == 1 ))
typeset a=2
(( a < 3 )) && (( a != 1 )) && echo "Execute code"
more details : http://faculty.salina.k-state.edu/tim/unix_sg/bash/math.html

Related

I am getting an error: line 5: conditional binary operator expected ; syntax error near `%' ; line 5: `if [[ $i % 2 = 0 ]]'

I am getting an error which is:
exam.sh: line 5: conditional binary operator expected
exam.sh: line 5: syntax error near `%'
exam.sh: line 5: `if [[ $i % 2 = 0 ]]'
Here is my program code:
#!/bin/bash
i=1;
for user in "$#"
do
if [[ $i % 2 = 0 ]]
then
cd even
mkdir $user
.
else if [[ $i % 3 = 0 ]]
then
cd three
mkdir $user
.
else
cd other
mkdir $user
fi
fi
i=$((i + 1));
done
[[ doesn't do arithmetics. You need (( for that.
if (( i % 2 == 0 ))
Another option is to use $((...)) to generate a C-style
"boolean" that you can test explicitly.
if [ "$(( x % 2 == 0 ))" = 1 ]; then
echo "$x is even"
fi
This is objectively worse than if (( x % 2 == 0 )) in bash, but is useful if you need strict POSIX compliance.

Values of an array not comparing to numbers correctly

Im trying to get an array from grades.txt, and determine what letter grade it should be assigned.
I either get
hw4part2.sh: line 26: [: : integer expression expected
If i use -ge or
hw4part2.sh: line 26: [: : unary operator expected
If i use >=
Below is the code im trying to get working
mapfile -t scores < grades.txt
numOScores=0
numOA=0
numOB=0
numOC=0
numOD=0
numOF=0
DoneWScores=0
A=90
B=80
C=70
D=60
F=59
while [ $DoneWScores -eq 0 ]
do
numOScores=$((numOScores + 1))
if [ "${scores[$numOScores]}" -ge "$A" ]
then
echo "A"
elif [ "${scores[$numOScores]}" -ge "$B" ]
then
echo "B"
elif [ "${scores[$numOScores]}" -ge "$C" ]
then
echo "C"
elif [ "${scores[$numOScores]}" -ge "$D" ]
then
echo "D"
elif [ "${scores[$numOScores]}" -le "$F" ]
then
echo "F"
else
echo "Done/error"
DoneWScores=1
fi
done
If anyone knows what my problem is, that'd be greatly appreciated
Consider this:
#!/usr/bin/env bash
if (( ${BASH_VERSINFO[0]} < 4 )); then
echo "Bash version 4+ is required. This is $BASH_VERSION" >&2
exit 1
fi
letterGrade() {
if (( $1 >= 90 )); then echo A
elif (( $1 >= 80 )); then echo B
elif (( $1 >= 70 )); then echo C
elif (( $1 >= 60 )); then echo D
else echo F
fi
}
declare -A num
while read -r score; do
if [[ $score == +([[:digit:]]) ]]; then
grade=$(letterGrade "$score")
(( num[$grade]++ ))
echo "$grade"
else
printf "invalid score: %q\n" "$score"
fi
done < grades.txt
for grade in "${!num[#]}"; do
echo "$grade: ${num[$grade]}"
done | sort

Unary operator expected error in while loop execution in shell scripting(UNIX)

I wrote a code to print
5 4 3 2 1
using while loop in shell script.
But error of expr: syntax error
scriptprog3.sh: line 3: [: -gt: unary operator expected
is showing. Please help out. Here is the code
a=5
while [ $a -gt 0 ]
do
echo $a
a=` expr $a -1 `
done
This is what you actually may want:
$ a=5
$ while (( a > 0 ));do echo $a ; (( a-- ));done
5
4
3
2
1
(( code )) makes the math over the a var without returning any value back to the caller.
I was executing the following code and it gave me the "[: -lt: unary operator expected"
error.
#while
i = 10
echo "This is a while loop"
while [ $i -lt 15 ]
do
echo $i
i=$[ $i+1 ]
done
The problem was using while loop as while [ $i -lt 15 ] like this,
so I changed it towhile [[ $i -lt 15 ]] and it worked (notice the double parentheses).
Below is the working example.
#while
i = 10
echo "This is a while loop"
while [[ $i -lt 15 ]]
do
echo $i
i=$[ $i+1 ]
done

Bash programming: evaluation in conditional statements

In bash scripting the if condition statement is not working properly with using "&&"
ARGCOUNT=$#
if (( "$ARGCOUNT" != "2" )) ;then
echo "number of arguments must be two"
fi
DFLAG=$1
HFLAG=$2
if (((( $DFLAG = "Mon" )) || (( $DFLAG = "MON" )) || (( $DFLAG = "mon" ))) && ((( HFLAG = "2" )) || (( HFLAG = "3" )) || (( HFLAG = "4" ))));then
echo " CS599 "
cd CS599
elif (((( $DFLAG = "Wed" )) || (( $DFLAG = "WED" )) || (( $DFLAG = "wed" ))) && ((( HFLAG = "2" )) || (( HFLAG = "3" )) || (( HFLAG = "4" ))));then
cd CS699
echo " CS699 "
elif (((( $DFLAG = "Fri" )) || (( $DFLAG = "FRI" )) || (( $DFLAG = "fri" ))) && ((( HFLAG = "2" )) || (( HFLAG = "3" )) || (( HFLAG = "4" ))));then
cd CS799
echo " CS799 "
else
echo "."
fi
my program is executing only else statement irrespective of arguments. means it evaluating if block false.
What is the problem ?
The parenthesis you use are for arithmetic evaluation. I think you are over using them, and it makes your script complicated.
This snippet below does work:
#!/bin/bash
ARGCOUNT=$#
if [ "$ARGCOUNT" -ne 2 ] ;then echo "number of arguments must be two"; fi
# put DFLAG in lower case (see man bash).
DFLAG=${1,,}
HFLAG=$2
if [ "$DFLAG" = 'mon' -a "$HFLAG" -ge 2 -a "$HFLAG" -le 4 ]; then
echo ok
else
echo failed
fi
As you can see, I optimized your expression:
Except for the case of $ARGCOUNT (which is safe because you initialized it to $#), don't forget to encase variable with double quote to avoid expansion.
In the declaration of DFLAG, I used the convert to lower case string operator (?). With that you won't have to check for each permutation of case in DFLAG. This might not work in bash3.
If you use the test or [ builtin, you can use -a between each expression to do a and.
Arithmetic evaluation with the test/[ builtin use the following operators: -ne (inequality), -eq (equality)-ge (greater or equal), -le (lesser or equals), -lt (lesser), -gt (greater).
As said in another answer, you can replace "$DFLAG" = 'mon' by "$DFLAG" == 'mon'. But this is not POSIX conformant (as said in my comment below) and I'm not enough knowledgeable on that to know if it's a good idea or not.
On a side note, if $HFLAG condition should always be the same, you can write your code like this:
if [ "$HFLAG" -ge 2 -a "$HFLAG" -le 4 ]; then
case "$DFLAG" in
mon|Mon|MON)
echo "monday";
;;
fry|Fry|FRY)
echo "friday";
;;
*)
echo "other"
;;
esac
fi
If that case, I putted back all permutation of case in case you were in bash3, to show you an example to do without ${DFLAG,}.
If you are looking for what mistake you did which is making condition to go to else part ...then it's simple mistake which almost every programmer do once in life ... using single "=" instead of "==" during comparison. Modify it accordingly and you should get expected flow/result in your script.
One eg.
$DFLAG = "Mon"
change to below notice the double equal sign
"$DFLAG" == "Mon"
First, you should go easy on the parenthesis. Those are fragile things.
Using Bash syntax (non-POSIX, less portable), you can write:
ARGCOUNT=$#
DFLAG=${1,,} # lower case
HFLAG=$2
# don't need the quotes in (( )) as we test arithmetic value
(( $ARGCOUNT != 2 )) && echo "number of arguments must be two"
shopt -s extglob # for #(1|2|3) below, see http://mywiki.wooledge.org/glob#extglob
if [[ $DFLAG = "mon" && $HFLAG == #(2|3|4) ]]; then
echo " CS599 "
cd CS599
if [[ $DFLAG = "wed" && $HFLAG == #(2|3|4) ]]; then
cd CS699
echo " CS699 "
if [[ $DFLAG = "fri" && $HFLAG == #(2|3|4) ]]; then
cd CS799
echo " CS799 "
else
echo "."
fi
Now you see how much you repeat yourself and can improve the algorithm. For instance, test HFLAG, if valid test DFLAG otherwise …
Read
Tests And Conditionals
Arithmetic Expression
Globbing extglob

Syntax error near unexpected token `if' in shell scripting

I was trying a sample program, to check the odd and even no's and was getting an error as below,
#!/bin/bash
N=10
for i in 1..N
if [$i/2 == 0]
then
echo "even"
else
echo "Odd"
fi
Error:
./case.sh: line 5: syntax error near unexpected token `if'
./case.sh: line 5: `if [$i/2 == 0]'
EDITED :
#!/bin/bash
N=10
for i in 1..N
do
if(( ($i/2) == 0 ));
then
echo "even"
else
echo "Odd"
fi
done
error :
./case.sh: line 6: ((: (1..N/2) == 0 : syntax error: invalid arithmetic operator (error token is "..N/2) == 0 ")
Odd
Correct working code :
#!/bin/bash
N=3
for (( i=1; i <= N; i++ ));
#for i in 1..N; // This didnt work
do
if [[ $i/2 -eq 0 ]]
#if (( i/2 == 0 )); // This also worked
then
echo "even"
else
echo "Odd"
fi
done
[ ] or [[ ]] needs spaces between its arguments. And in your case you should use [[ ]] or (( )) as [ ] can't handle division along with comparison:
if [[ 'i / 2' -eq 0 ]]; then
if (( (i / 2) == 0 )); then
for i in 1..N; do should also be
for (( i = 1; i <= N; ++i )); do
You probably meant to have a form of brace expansion, but you can't apply a parameter name on it:
{1..10} ## This will work.
{1..N} ## This will not work.
Using eval may fix it but better go for the other form of for loop instead.
Try this :
#!/bin/bash
N=10
for i in $(seq 1 $N); do
if [ `expr $i % 2` -eq 0 ]
then
echo "even"
else
echo "Odd"
fi
done
1..N is not a valid syntax in bash(though I think you might be coming from ruby background), you can use seq.

Resources