Bash script ignores the negative prefix on negative numbers - bash

a=4;
b=7;
c=5;
x =[ a-b ]
if (x -gt c) then {
echo "x is greater"
} else {
echo " something"
}
I want to compare x and c ignoring the negative prefix of c.

I'm assuming you meant "negative prefix of x". There are a ton of errors in your code, are you sure you're writing in bash?
#!/bin/bash
typeset a=4 b=7 c=5
x=$(( a - b ))
x=${x//-/}
if [[ x -gt c ]]; then
echo "x is greater"
else
echo " something"
fi

Related

Comparing numbers using Bash

I wrote a script to compare two numbers:
#!/bin/bash
read X
read Y
if [[ $X -le $Y ]];
then
echo "X is less than Y"
elif [[ $X -ge $Y ]];
then
echo "X is greater than Y"
else
echo "X is equal to Y"
fi
For some reason when the value of X and Y are the same, the else condition is not executed. Instead the if [[ $X -le $Y ]]; is executed.
When I change the position of the if and else conditions:
#!/bin/bash
read X
read Y
if [[ $X -eq $Y ]];
then
echo "X is equal to Y"
elif [[ $X -ge $Y ]];
then
echo "X is greater than Y"
else
echo "X is less than Y"
fi
The else condition is executed for this case. Can someone please give me an explanation to why the else condition is executed for one case but not the other?
-le and -ge are like <= and >=.
-le = less than or equal
-ge = greater than or equal
-lt = less than
-gt = greater than
It'll work if you switch to -lt and -gt:
if [[ $X -lt $Y ]]
then
echo "X is less than Y"
elif [[ $X -gt $Y ]]
then
echo "X is greater than Y"
else
echo "X is equal to Y"
fi
You can also use (( )) for arithmetic operations. It has more natural syntax: you can use < and >, you don't need spaces around the operators, and $ dollar signs are optional.
if ((X < Y))
then
echo "X is less than Y"
elif ((X > Y))
then
echo "X is greater than Y"
else
echo "X is equal to Y"
fi

Compare Numbers not working properly (Bash Script in Hacker Rank)

According to the problem stated in the below link:
https://www.hackerrank.com/contests/bash-and-linux-shell-practice/challenges/bash-tutorials---comparing-numbers/problem
My code is working fine in Mac OSX terminal, but while submitting the same code in Hackerrank one of the test case is failing. I am not sure why this is happening. Would really appreciate any answers.
read X
read Y
if [[ $X > $Y ]]
then
echo "X is greater than Y"
elif [[ $X < $Y ]]
then
echo "X is less than Y"
else
echo "X is equal to Y"
fi
HackerRank Custom Test Case:
Compilation Successful
Input (stdin)
-100
100
Your Output
X is greater than Y
I'm not sure why you're getting that result; I get "X is less than Y" in actual bash. However, your script is actually wrong in a different way: in [[ ]], < and > do alphabetic comparison rather than numeric comparison. To understand the difference, consider that [[ 5 < 1000 ]] will come out as false, because "5" comes after "1" in character sorting order. To do numeric comparison, use -lt and -gt instead.
You can use the Bash double-parenthesis context ((...)) vs test context [[ ... ]] to get more typical arithmetic comparisons:
x=-5
y=5
if ((x>y)); then
echo "X is greater than Y"
elif ((x<y)); then
echo "X is less than Y"
else
echo "X is equal to Y"
fi
Or use an integer comparison inside [[ ... ]] test:
if [[ "$x" -gt "$y" ]]; then
echo "X is greater than Y"
elif [[ "$x" -lt "$y" ]]; then
echo "X is less than Y"
else
echo "X is equal to Y"
fi
Inside [[ ... ]] the <,> or == tests string comparisons.
Both of these methods only work with integers; to use floats, you need to use awk, bc or other float interpreter. Be sure to use double quotes "$x" in the [[ test ]] and the quotes and sigil are not required for (( ))
With user input, be sure to test that $x and $y are actual
numbers. Good tests here...

When running bash script there is a logical error

So I have fixed my first issue with the script taking input but now no matter what letter I enter it only adds the numbers.
here is the code. any help would be greatly appreciated.
#!/bin/bash
add() {
expr $x + $y
}
sub() {
expr $x - $y
}
mult() {
expr $x * $y
}
div() {
expr $x / $y
}
echo "Enter a for add, s for subtract, m for multiply or d for divide and 2 numbers"
read choice x y
if [ $choice=="a" ]
then
add
else
if [ $choice == "s" ]
then
sub
else
if [ $choice == "m" ]
then
mult
else
if [ $choice == "d" ]
then
div
fi
fi
fi
fi
It seems like you want to get x and y from first and second arguments ( $1 and $2 ) and to read the operation ( a, s, d, m ) from stdin.
I modified your code a bit, to overcome the problems in the original script and to provide the result based on my assumptions:
#!/bin/bash
# First number.
x=$1
# Second number.
y=$2
# Result of either addition, subtraction, division or multiplication of $x and $y.
result=0
# Reads operation from user.
read -ep "Enter a for add, s for subtract, m for multiply or d for divide: " operation
case $operation in
a) result=$(( x + y ));;
s) result=$(( x - y ));;
d) result=$(( x / y ));;
m) result=$(( x * y ));;
*) printf '%s: %s\n' "$operation" "Unknown operation" >&2; exit 1;;
esac
printf 'result: %s\n' "$result"
Usage example: ( script name is sof.sh )
./sof.sh 5 4
Enter a for add, s for subtract, m for multiply or d for divide: a
result: 9
./sof.sh 5 4
Enter a for add, s for subtract, m for multiply or d for divide: m
result: 20
./sof.sh 5 4
Enter a for add, s for subtract, m for multiply or d for divide: s
result: 1
./sof.sh 5 4
Enter a for add, s for subtract, m for multiply or d for divide: d
result: 1
P.S.
Please note the following:
expr is a program used in ancient shell code to do math. In POSIX shells like bash, use $(( expression )). In bash, ksh88+, mksh/pdksh, or zsh, you can also use (( expression )) or 'let
expression'.
Though not used originaly in the script, while programming in Bash it is worth knowing that [[ is a bash keyword similar to (but more powerful than) the [ command. See this Bash FAQ and Test and conditionals.
Unless you're writing for POSIX sh, it is recommended to use [[.
First of all, you want the script to read the values from the standard input, but you are recovering it from the arguments.
Second, you are not passing parameters to the functions.
Third, you are not using parameters inside the functions.
Fourth, you are not letting spaces between operators when using expr.
NOTE: Rany Albeg Wein remarked that this bash guide is outdated, and he recommends this one. Also i recommend the GNU official guide (other formats).
So, assuming that you want to use your script like ./my-script.sh m 2 3 , here is your code, but working:
#!/bin/bash
add() {
expr $1 + $2
}
sub() {
expr $1 - $2
}
mult() {
expr $1 \* $2
}
div() {
expr $1 / $2
}
echo "Enter a for add, s for subtract, m for multiply or d for divide and 2 numbers"
x=$2
y=$3
if [ $1 == "a" ]
then
add $x $y
else
if [ $1 == "s" ]
then
sub $x $y
else
if [ $1 == "m" ]
then
mult $x $y
else
if [ $1 == "d" ]
then
div $x $y
fi
fi
fi
fi
And finally this is your script minimally modified to read the data from the standard input:
#!/bin/bash
add() {
echo "Result:"
expr $1 + $2
}
sub() {
echo "Result:"
expr $1 - $2
}
mult() {
echo "Result:"
expr $1 \* $2
}
div() {
echo "Result:"
expr $1 / $2
}
echo "Enter a for add, s for subtract, m for multiply or d for divide and 2 numbers"
read operation
echo "Read first parameter"
read x
echo "Read second parameter"
read y
if [ $operation == "a" ]
then
add $x $y
else
if [ $operation == "s" ]
then
sub $x $y
else
if [ $operation == "m" ]
then
mult $x $y
else
if [ $operation == "d" ]
then
div $x $y
fi
fi
fi
fi
Also, if you had some troubles, you could add debugging messages to the script just setting #!/bin/bash -xv at the beginning of the script.

bash while loop comparison not evaluating

I am trying to understand the difference between coding for if and while statements in bash.
In the script below, if I use IF I get the expected result using == OR -eq etc. However with the while loop each while seems to evaluate as true for all tests. While loops 1 & 3 should fail, correct?
A != B,
A == B,
A == C
I have tried different combinations of [ "" "" ] or [[ "" "" ]] etc.
What is the correct syntax for while
thx
Art
#!/bin/sh
set -x
myVarA="abc"
myVarB="abc"
myVarC="def"
while [[ ${myVarA} != ${myVarB} ]]
echo "A does not equal B"
i=$(($i+1))
do sleep 1s
break
done
while [[ ${myVarA} == ${myVarB} ]]
echo "A does equal B"
i=$(($i+1))
do sleep 1s
break
done
while [[ ${myVarA} == ${myVarC} ]]
echo "A does equal C"
i=$(($i+1))
do sleep 1s
break
done
renders the following,
+ myVarA=abc
+ myVarB=abc
+ myVarC=def
+ [[ abc != abc ]]
+ echo 'A does not equal B'
A does not equal B
+ i=1
+ sleep 1s
+ break
+ [[ abc == abc ]]
+ echo 'A does equal B'
A does equal B
+ i=2
+ sleep 1s
+ break
+ [[ abc == def ]]
+ echo 'A does equal C'
A does equal C
+ i=3
+ sleep 1s
+ break
Your do keywords are wildly misplaced.
Everything between while and do is the condition list.
So your condition list in the first block is
[[ ${myVarA} != ${myVarB} ]]; echo "A does not equal B"; i=$(($i+1))
which, as you might imagine, evaluates as true since i=$(($i+1)) evaluates as true.
Similarly for the other blocks.
Move the do to the end of the while lines
while [[ ${myVarA} != ${myVarB} ]]; do
: do something
done

Check if a number is even in shell

I need to check if a number is even.
Here's what I've tried.
newY="281"
eCheck=$(( $newY % 2 ))
echo $newY
echo $eCheck
while [ $eCheck -eq 0 ]; do
newY=$((newY-1))
eCheck=$(( $newY % 2 ))
echo $newY
done
...
returns eCheck = 1
how can it be? 281/2 = 140.5
i've also tried using bc, but it went into an infinite loop eCheck=$(echo "scale=1;$newY%2" | bc)
Nici is right, "%" is the modulo, and gives you the remainder of the division.
Your script can be simplified as follows :
if [[ $((var % 2)) -eq 0 ]];
then echo "$var is even";
else echo "$var is odd";
fi
You can do a simple :
eCheck=$(( $newY & 1 ))
to utilize the bitwise operators in bash.
The % operator computes the remainder. So 281 % 2 is 1, because 281 divided by 2 is 140 with a remainder of 1.
#!/usr/bin/env bash
[[ $( expr $1 % 2 ) -eq 0 ]] && echo "Even Number" || echo "Odd Number"
You are so close! Think of it like this. There are only two possible answers for Y in the expression
Y = X % 2
for ALL values of X. What are they? Play with a few values of X to see if you can come up with the values for Y.
Next, is there anything you can determine about what the value of Y says about the value of X? That is, can you use the value of Y to answer the problem you are trying to solve?
This can be done using expr
evenCheck=$(expr $newY % 2)
if [ $evenCheck = 0 ] ;
then echo "number is even";
else echo "number is odd";
fi
done
As you mention you are checking even for single no, So there is no need to use a loop. Here is my bit of code.
read -p "Enter a number: " num
if [ $((num%2)) -eq 0 ]
then
echo "Entered Number is even:"
else
echo "Entered Number is odd:"
fi
Since this question is tagged as Bash, the right way to check if a number is even in Bash is:
if ((num%2 == 0)); then
echo "The number is even"
fi
or, more even shorter:
if ((num % 2)); then
echo "The number is even"
fi
We don't need to use [[ ... ]] in this case.
See also:
Difference between Bash operators double vs single brackets and (( (on Unix & Linux Stack Exchange)
How do I check whether a variable has an even numeric value?
#!bin/bash
echo "Type the input integer, followed by [Enter]:"
read x
if [ $((x%2)) -eq 0 ]; then
echo "$x is even"
else
echo "$x is odd"
fi
Yes "%" is modulo, it gives you the remainder like others have mentioned

Resources