Bash; conditional statement echoing numbers - bash

I'm nearly done writing a script for an assignment, but am having some trouble thinking of how to do this final part.
My problem is within a while loop; it prints out the number based on the IF statements, the number entered will always be an even number.
The IFs aren't connected by else/elif because the number should be able to printed out if it applies to more than 1 of the statements.
I want to print $starting on every loop if it doesn't meet any of the IF conditions, but if it does I don't want to print it. Can anyone see how to do that?
while [[ $starting -lt $ending ]]; do
if [ $((starting %7)) -eq 0 ]
then
echo "$starting red"
fi
if [ $((starting % 11)) -eq 0 ]
then
echo "$starting green"
fi
if [ $((starting % 13)) -eq 0 ]
then
echo "$starting blue"
fi
starting=$((starting + 2))
done

Keep track of whether you've done what you want to do in a variable:
while [[ $starting -lt $ending ]]; do
handled=0
if [ $((starting %7)) -eq 0 ]
then
echo "$starting red"
handled=1
fi
if [ $((starting % 11)) -eq 0 ]
then
echo "$starting green"
handled=1
fi
if [ $((starting % 13)) -eq 0 ]
then
echo "$starting blue"
handled=1
fi
if ! (( handled ))
then
echo "$starting didn't match anything"
fi
starting=$((starting + 2))
done

Add another if at the end that checks if none of the previous if statements are true. if !(starting%7==0 or starting%11==0 or starting%13==0) => echo starting

Related

How to call another script within a script with bash

Hello here is my primary script. The test2.sh is just an echo "it worked"
what happens when I try and call from the original loop, it gets to the correct file then echo's infinite "it worked" where it should just be doing it once.
Any idea why? I really want to have another loop called outside of the main script that won't interfere, but still learning bash =P
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh & continue
fi
sleep 5
((number++))
echo $number
done
first observation & is not a logical operator, & runs the precedding command in the background. Use && for logical operations.
what you need is a break keyword not a continue keyword . If you use the break keyword, the loop will stop executing. The continue keyword only rexecutes the loop , and since number is 4 , this branch of code will always run elif [ "$number" -eq "4" ]; then
working code
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh && break
fi
sleep 5
((number++))
echo $number
done
or you can do this
for number in {1..4};do
(( number == 4 )) && ./test2.sh || echo "$number"
sleep 5
done

How do I make this bitwise code more concise?

My bitwise code which works is:
#!/bin/bash -e
random=$((RANDOM % 32));
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
echo "random=${random}";
if [ $(bitWiseAnd ${random} "0x10") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x8") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x4") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x2") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x1") -ne 0 ]; then
echo "1"
else
echo "0"
fi
A sample output from the above code:
random=15
0
1
1
1
1
I have no idea how this code works. Can this code be made more concise?
You could use a for loop instead of repeated if blocks. Also, the for loop spells out your purpose more clearly, like this:
#!/bin/bash -e
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
random=$((RANDOM % 32));
echo "random=${random}";
for i in 10 8 4 2 1; do
if [ $(bitWiseAnd ${random} "0x$i") -ne 0 ]; then
echo "1"
else
echo "0"
fi
done
Output:
random=10
0
1
0
1
0
Also, the function below
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
could be made more explicit this way, as long as we are looking at just two input arguments:
bitWiseAnd() {
printf "%s\n" $(($1 & $2))
}
This won't produce the exact same output as you need, because you asked for an optimization and it doesn't involve multiple useless echo statements.
Another approach would be using a while-loop and check if bit-positions are still valid. I have removed the useless echo statements, assuming you don't need any of that and just want to improve the code.
bitMask="0x10"
while [ $(bitWiseAnd "31" "$bitMask") -ne 0 ] && ((bitMask))
do
bitMask=$((bitMask >> 1))
done
Just replace the hard-coded number 31 with the variable value $random and bitMask of your choice.

unix all if statements in one place

I am newly learning shell script ! i tried following code but i have error
line 15: syntax error near unexpected token `elif
#!/bin/bash
read -p "Enter the number : " n
if [ $n -eq 1 ]
then
echo "$n is equal to 1 true"
elif [ $n -lt 4 ]
then
echo "$n is less than value of 4 ture"
else
echo "$n is not less then value of 4 false"
elif [ $n -gt 10 ]
then
echo "$n is greater than the value of 10 true"
else
echo "$n is not greater than the value of 10 false"
if [ $n -ge 0 ]
then
echo "$n is greater than or equal to 0"
else
echo "$n is not greater than or equal to 0"
fi
else
"Bye"
fi
Can anyone help ?
It's a bit hard to tell what your intention is. The correct answer depends on what you want to do here. My guess is that you want this:
if [ $n -eq 1 ]
then
echo "$n is equal to 1 true"
elif [ $n -lt 4 ]
then
echo "$n is less than value of 4 true"
elif [ $n -gt 10 ]
then
echo "$n is greater than the value of 10 true"
elif [ $n -ge 0 ]
then
# This will be true if $n is >= 4 and <= 10
echo "$n is greater than or equal to 0"
else
# Negative
"Bye"
fi

If statement with two or more conditions

I was modifying an script didn't know how to write more than one condition in an if statement. I want to connect the two condition with an AND.
if [ envoi1 -eq 2 ];then
if [ envoi2 -eq 0 ];then
echo 'Ahora mismo.'
envoi = 1
fi
else
if [ envoi2 -eq 1 ];then
if [ envoi1 -eq 1 ];then
echo 'Situacion Normal.'
envoi = 1
fi
else
echo 'Raruno'
envoi=`expr $envoi1 + envoi2`
fi
fi
Now i use nested if to do the same but the code it's not so clear for me.
try this:
if [ $envoi1 -eq 2 ] && [ $envoi2 -eq 0 ] ; then
envoi = 1
fi
In bash, you can use [[ as follows:
if [[ $envoi2 -eq 1 && $envoi1 -eq 1 ]]; then
echo "Situacion Normal."
envoi=1
fi
However, [[ is not POSIX and will not work if you are using the /bin/sh shell. So if portability is desired use:
if [ $envoi2 -eq 1 -a $envoi1 -eq 1 ]; then
echo "Situacion Normal."
envoi=1
fi
Also note that when assigning variables you should not have any spaces on either side of the =.

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