please take a look at this:
This should echo X10, but echoes jackpot... can anyone see why it doesn't behave as it should?
Probably just some mistake I made that do not throw errors?
dice1=1
dice2=40
#These two lines are just tests to see if my brain still function:
echo "Is dice 1 less than 2? $(($dice1 < 2))"
echo "Is dice 2 between 6 and 54? $(($dice2 > 5 && $dice2 < 55))"
if [[ $dice1 == 1 ]]
then
if [[ $dice2 < 6 ]]
then
#dice1 has to be equal 1 and dice2 less than 6:
echo "jackpot"
else
#Since dice2 is larger than 5, if smaller than 55
#it should be between 6 and 54...
if [[ $dice2 < 55 ]]
then
echo "X10"
else
echo "X5"
fi
fi
else
echo "Dice one is not equal 1."
fi
When used with [[, the < and > operators sort lexicographically using the current locale.
I see two options.
Do the comparison in arithmetic context:
if (( $dice1 == 1 ))
then
if (( $dice2 < 6 ))
or the old-fashioned way:
if [[ $dice1 -eq 1 ]]
then
if [[ $dice2 -lt 6 ]]
Related
We have a text file with 4 lines and a different number of words and i want to count the words per line and see if the number is even or odd but the result keeps saying
./oddwords.sh: line 14: syntax error near unexpected token `then'
./oddwords.sh: line 14: ` if[ n % 2 == 0 ]; then'
This is what ive done so far
#!/bin/bash
if [ $# -ne 1 ] ; then
{
echo "Wrong number of arguments!"
exit 1
}
fi
while read line ; do
n= echo "$(echo $line | wc -w)"
if[ n % 2 == 0 ]; then
echo "Is even"
else
echo "Is odd"
fi
done < $1
Using double brackets like
if [[ n % 2 == 0 ]]; then
and making the numbers variables at the top instead of just saying 2
a=2
b=1
at the beginning then referencing them later in the if statement like
if [[ $a%2 == 0 ]]; then
if you still have issues try
if [[ $a%2 -eq 0 ]]; then
Here are a couple sites i find useful for checking bash when I get stuck on something as well.
https://www.shellcheck.net/
https://explainshell.com/
The variable D is supposed to contain a positive integer. My FizzBuzz program has to use arithmetic substitution and the ||, &&, () operators. If the number is a multiple of three, the program should output the word Fizz; if the number is a multiple of five, the word Buzz. If the number is a multiple of three and five, then the program should display the word FizzBuzz. I am a novice programmer, unsure where I have gone wrong.
"""
#!/bin/bash
D=5
if [ $D % 3 == 0 ] ;
then
echo "Fizz"
elif [[ $D % 5 == 0 ]]
then
echo "Buzz"
elif [[ $D % 3 == 0 && $D % 5 == 0 ]]
fi
echo "FizzBuzz"
done
"""
To perform computations I recommend (( and )):
#!/bin/bash
d=5
if (( $d%3 == 0 && $d%5 == 0 )); then
echo "FizzBuzz";
else
if (( $d%3 == 0 )); then
echo "Fizz"
elif (( $d%5 == 0 )); then
echo "Buzz"
fi
fi
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
We have some scripts that do things like
e=$?
if [[ $e == 123 ]]; then exit 1; fi
They're more complicated than that, it's just an example. My question is using double brackets acceptable to make numerical comparisons this way, is there any disadvantage? I would think it should be double parentheses if (( $e == 123 )) but I don't want to go changing a lot of scripts over nothing.
Thanks
There are a lot of key differences doing it, because == checks for exact string equality, but -eq evaluates both expressions arithmetically before checking for equality.
$ [[ " 1 " -eq 1 ]] && echo equal || echo not
equal
$ (( " 1 " == 1 )) && echo equal || echo not
equal
$ [[ " 1 " = 1 ]] && echo equal || echo not
not
Also, the empty string happens to be numerically equal to zero:
$ [[ "" -eq 0 ]] && echo equal || echo not
equal
$ [[ "" == 0 ]] && echo equal || echo not
not
And a whole other class of differences appears when you bring the comparison operators in - considering < vs -lt, for instance:
$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ (( 2 < 10 )) && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not
This is because the string 2 is alphabetically after the string 10 (since 1 comes before 2), but the number 2 is numerically less than the number 10.
Credits to the original cross site duplicate, with a few updates Is there any major difference when comparing a variable as a string or as an int?
The verdict is to use $((..)) for arithmetic comparisons strictly to avoid interpreting the operands as strings.
I used a while read loop in shell script to count and number line by line my file.txt. Now I want to give, inside the loop, the exact number of lines, like if I'm command wc -l. Below is my script.
#!/bin/bash
let count=0
while read cdat ctim clat clon
do
h=${ctim:0:2}; # substring hours from ctim
m=${ctim:3:2};
s=${ctim:6:2};
# echo $j
if [[ $h>=11 ]]; then
if [[ $h<=18 ]] && [[ $s<=00 ]]; then
if [[ $m != 01 ]]; then # spaces around "!=" is necessary
echo "$count $LINE" $cdat $ctim $clat $clon
let count=$count+1
fi
fi
fi
done < cloud.txt
exit
And output contains lines like:
0 2014/04/00 14:44:00 26.12 -23.22
1 2014/11/21 16:05:00 19.56 -05.30
2 2014/01/31 13:55:00 02.00 31.10
3 2014/04/00 14:20:00 17.42 12.14
4 2014/07/25 15:30:00 35.25 05.90
5 2014/05/15 12:07:00 23.95 07.11
6 2014/07/29 17:34:00 44.00 17.43
7 2014/03/20 18:00:00 -11.12 -22.05
8 2014/09/21 12:00:00 06.44 41.55
My question is how to find that the output contains 9 lines?
This does not answer your specific question
if [[ $h>=11 ]]; then
if [[ $h<=18 ]] && [[ $s<=00 ]]; then
All of those tests always return true.
The test, [ and [[ commands act differently based on the number of arguments they see.
All those tests have 1 single argument. In that case, if it's a non-empty string, you have a success return code.
Crucial crucial crucial to put whitespace around the operators.
if [[ $h >= 11 ]]; then
if [[ $h <= 18 ]] && [[ $s <= 00 ]]; then
Question for you: what do you expect this test to do? [[ $s <= 00 ]]
Be aware that these are all lexical comparisions. You probably want this instead:
# if hour is between 11 and 18 inclusive
if (( 10#$h >= 11 && 10#$h <= 18 )); then
You already know this value with $count. Since you're counting from 0, the number you want is $count+1.
If I add the command "wc -l" at the end of my loop, I can get exactly what I wanted, means that number of lines (9 lines). But I want to know if there is a way to get it exactly inside the loop, maybe using the same command "wc -l" or not.
#!/bin/bash
let count=0
while read cdat ctim clat clon
do
h=${ctim:0:2}; # substring hours from ctim
m=${ctim:3:2};
s=${ctim:6:2};
if [[ $h>=11 && $h<=17 ]] || [[ $ctim == "18:00:00" ]]; then
echo "$count $LINE" $cdat $ctim $clat $clon
let count=$count+1
fi
done < cloud.txt | wc -l
exit
The result is exactly: 9
But now how to do it inside the loop?