Multiple conditions in case statement, bash - linux

read X;
read Y;
read Z;
if [[ $X,$Y,$Z -ne "0" ]]; then
if [[ $X,$Y,$Z -ge 1 && $X,$Y,$Z -le 1000 ]] && [[ $((X+Y)) -gt $Z || $((Y+Z)) -gt $X || $((X+Z)) -gt $Y ]]; then
case $X,$Y,$Z in
$X -eq $Y && $Y -eq $Z && $X -eq $Z ) echo "EQUILATERAL";;
esac
else
echo "bye";
fi
fi
*./bashtesting.sh: line 7: syntax error near unexpected token `-eq
./bashtesting.sh: line 7: $X -eq $Y && $Y -eq $Z && $X -eq $Z ) echo "EQUILATERAL";;*
how to equate the three variables at a time?

This is how I would do it, with a loop and associative array.
#!/usr/bin/env bash
for h in x y z; do
read -rp 'Enter input: ' input
if [[ -z $input ]]; then
printf >&2 '%s is empty, please try again!\n' "${input:-input}"
exit 1
elif [[ $input != *[0-9]* ]]; then
printf '%s is not an int, please try again!\n' "$input"
exit 1
else
declare -A num[$h]=$input
fi
done
for i in "${num[#]}"; do
if ! (( i == 0 )); then
for j in "${num[#]}"; do
if (( j > 1 && j < 100 )); then
if (( (num[x] + num[y]) > num[z] || (num[y] + num[z]) > num[x] || (num[x] + num[z]) > num[y] )); then
if (( num[x] == num[y] && num[y] == num[x] && num[x] == num[z] )); then
echo equilateral
break 2
fi
fi
fi
done
fi
done
It it not pretty, It looks like an Anti Pattern, and there might be a better way to do it but this will get you there I suppose.

Related

can someone help me make this code smaller?

I need to upload this code, but the code is too large and confusing, can someone possibly help me to summarize this code or make it smaller? Its only the input part which's kinda confusing.
input(){
while read line;
do
for name in $line;
do
if [ "$name" == "`cat /etc/passwd | cut -f1 -d: | grep "^$name"`" ]
then
#echo $name----------
if [[ $s -eq 0 && $l -eq 0 && $i -eq 0 && $I -eq 0 && $u -eq 0 ]]; then
standard
fi
if [ $s -eq 1 ]
then
keepSudoUser
fi
if [ $l -eq 1 ]
then
interactiveShell
fi
if [ $i -eq 1 ]
then
userUnder1000
fi
if [ $I -eq 1 ]
then
userOver1000
fi
if [ $u -eq 1 ]
then
excludeUser
fi
fi
NO=0
done
done
}
input
This is more compact:
input() {
while read -ra names; do
for name in "${names[#]}"; do
if grep -q "^${name}:" /etc/passwd; then
[[ "$s$l$i$I$u" == "00000" ]] && standard
(( s == 1 )) && keepSudoUser
(( l == 1 )) && interactiveShell
(( i == 1 )) && userUnder1000
(( I == 1 )) && userOver1000
(( u == 1 )) && excludeUser
fi
NO=0
done
done
}
input
A more strict translation would be
((s == 0 && l == 0 && i == 0 && I == 0 && u == 0)) && standard
# or
(( !(s || l || i || I || u) )) && standard

linux bash shell error - error syntax error in conditional expression

i don't understand this error that is always giving me, can you pls help me?
I am doing a homework and is really important and I am trying to figure out how to solve it since this early morning
param0="KcgMy4kfBovoomVUcvtkxXqh1xosedAq";
param1="r2UmsEnodjLin2zT94M7eAX76vpB7gTe";
param2=97;
output="";
f=0;
for (( i=0, j=0; i<${#param0}, j<${#param1}; i++, j++ ));
do c0=${param0:$i:1};
c1=${param1:$j:1};
renum="^[0-9]+$";
if [[ $c0 =~ $renum && $c1=~ $renum ]];
then param2=$((param2 - i - (c0 * c1)));
if (( param2 < 1 ));
then param2=$((-1 * param2));
f=$((!f));
fi;
output+=${param2};
else reupper="^[A-Z]+$";
if [[ $f -eq 1 && $c0 =~ $reupper ]];
then output+=${c0};
else output+=${c1}${c0};
fi;
fi;
if [[ $c0 =~ $realpha && $c1 =~ $realpha ]];
then reverse="";
for ((k = ${#output} - 1; k >= 0; k--));
do reverse=${reverse}${output:$k:1};
done;
output=$reverse;
fi;
done;
echo ${output:0:32};
Fixed missing space at the second Regex.
Don't forget to check your script with https://shellcheck.net/ or use a text editor with this as a plug-in.
Fixed your script:
#!/usr/bin/env bash
param0="KcgMy4kfBovoomVUcvtkxXqh1xosedAq"
param1="r2UmsEnodjLin2zT94M7eAX76vpB7gTe"
param2=97
output=""
f=0
for ((i = 0, j = 0; i < ${#param0}, j < ${#param1}; i++, j++)); do
c0=${param0:i:1}
c1=${param1:j:1}
renum="^[[:digit:]]+$"
if [[ $c0 =~ $renum && $c1 =~ $renum ]]; then
param2=$((param2 - i - (c0 * c1)))
if ((param2 < 1)); then
param2=$((-1 * param2))
f=$((!f))
fi
output+=${param2}
else
reupper="^[[:upper:]]+$"
if [[ $f -eq 1 && $c0 =~ $reupper ]]; then
output+=${c0}
else
output+=${c1}${c0}
fi
fi
realpha="^[[:alpha:]]+$"
if [[ $c0 =~ $realpha ]] && [[ $c1 =~ $realpha ]]; then
reverse=""
for ((k = ${#output} - 1; k >= 0; k--)); do
reverse=${reverse}${output:k:1}
done
output=$reverse
fi
done
printf %s\\n ${output:0:32}

If statement 3 conditions Bash

I want to do an if statement with three conditions that have to be satisfied at the same time. I am using Ubuntu Bash for Windows and the values $c1, $c2 and $c3 are non-integer (decimal negative numbers).
if [ (( $(echo "$c1 < 0" | bc -l) )) ] && [ (( $(echo "$c2 < 0" | bc -l) )) ] && [ (( $(echo "$c3 < 0" | bc -l) )) ];
then
>&2 echo -e " ++ Constraints OK"
else
>&2 echo -e " ++ Constraints WRONG"
fi
However, I get the following syntax error in the if line: syntax error near unexpected token `('
If I just put one condition:
if (( $(echo "$c1 < 0" | bc -l) ));
it works, but when I add the three of them as AND (&&), I get the error. Can anyone help me?
Considerably more efficient (assuming you know your values are numbers, and only need to check whether they're all negative) would be:
if [[ $c1 = -* ]] && [[ $c2 = -* ]] && [[ $c3 = -* ]]; then
>&2 echo " ++ Constraints OK"
else
>&2 echo " ++ Constraints WRONG"
fi
If you want to be more specific about the permissible formats (f/e, allowing leading spaces), a regex is another option, which similarly can be implemented more efficiently than spawning a series of subshells invoking bc:
nnum_re='^[[:space:]]*-([[:digit:]]*[.][[:digit:]]+|[[:digit:]]+)$'
if [[ $c1 =~ $nnum_re ]] && [[ $c2 =~ $nnum_re ]] && [[ $c3 =~ $nnum_re ]]; then
>&2 echo " ++ Constraints OK"
else
>&2 echo " ++ Constraints WRONG"
fi
First, pass the relational AND operators into bc to get rid of some punctuation (also only invokes bc once):
if (( $(echo "$c1 < 0 && $c2 < 0 && $c3 < 0" | bc -l) == 1 ))
then
>&2 echo -e " ++ Constraints OK"
else
>&2 echo -e " ++ Constraints WRONG"
fi
Although if it were me, I would create a shell function returning a "true" exit status if bc evaluates the result of an expression to non-zero. Then you can hide most of the ugly punctuation in one place separated from your main logic:
function bc_true() {
(( $(echo "$#" | bc -l) != 0 ))
}
And write a (IMO) cleaner shell expression:
if bc_true "$c1 < 0 && $c2 < 0 && $c3 < 0"
then
...

check if a number is a prime in bash

I am trying to write a bash script to find if a number is prime, but i can't find what is wrong with my script
#!/bin/bash
#set -x
echo -n "enter a number "
read isPrime
count=2
x=0
while [ $count -lt $isPrime ]; do
if [ `expr $isPrime % $count`-eq 0 ]; then
echo "not prime"
fi
count=`expr $count + 1`
done
echo " it is prime"
#set +x
Using factor would be easy. But if you somehow need a script, I would implement something like following. I'm not sure whether this is the best algorithm, but this is way efficient than yours.
function is_prime(){
if [[ $1 -eq 2 ]] || [[ $1 -eq 3 ]]; then
return 1 # prime
fi
if [[ $(($1 % 2)) -eq 0 ]] || [[ $(($1 % 3)) -eq 0 ]]; then
return 0 # not a prime
fi
i=5; w=2
while [[ $((i * i)) -le $1 ]]; do
if [[ $(($1 % i)) -eq 0 ]]; then
return 0 # not a prime
fi
i=$((i + w))
w=$((6 - w))
done
return 1 # prime
}
# sample usage
is_prime 7
if [[ $? -eq 0 ]]; then
echo "not a prime"
else
echo "it's a prime"
fi
You can find an explanation about the used algorithm here

comparison of integer and floating point numbers in shell script

In shell script how can we compare (integer and floating point) ,(flaoting point and floating point),(floating point and integer),(integer and integer) with only one if condition.
i have few examples like
set X=3.1
set Y=4.1
if [ $X < $Y ] then
echo "wassup"
endif
But running the above from cron job doesnt seem to work.
The way to carry out floating point operations in bash is to use bc which is available on almost all linux distributions.
# bc will return 0 for false and 1 for true
if [ $(echo "23.3 > 7.3" | bc) -ne 0 ]
then
echo "wassup"
fi
There's a good article available on linux journal about floating point math in bash using bc.
Bah itself only handles integers. Use bc:
echo "$X>$Y" | bc
0
echo "$X<$Y" | bc
1
You don't need to worry about scale. It is just for the preocision of output formats:
X=3.000001
Y=3.0001
echo "$X>$Y" | bc
0
echo "$X<$Y" | bc
1
echo "scale=1;$X<$Y" | bc
1
below example works on bash shell.
X=3.1
Y=4.1
if [ $X -le $Y ]
then
echo "wassup"
fi
you may want to learn shell script here
EDIT. based on the comments to this answer (thanks to user unknown and glenn jackman), it seems that when using bc for a true/false test, the required bash test is simply:
(( $(echo "$X < $Y" |bc) )) ... see the test results and script below
wheras, the comparison to -ne 0 is needed for the old style bash [ ] test.
bash does not natively handle floating point numbers, but you can call a utility such as bc
From man bc - An arbitrary precision calculator language
X=3.1
Y=4.1
# This test has two superfluous components.
# See EDIT (above) and TESTS below
if (($(echo "scale=9; $X < $Y" |bc)!=0)) ;then
echo "wassup"
fi
TEST results:
if [ "1" ] true
[ "1" ] true
if [ "0" ] true
[ "0" ] true
if [ 1 ] true
[ 1 ] true
if [ 0 ] true
[ 0 ] true
if (( "1" )) true
(( "1" )) true
if (( "0" )) false
(( "0" )) false
if (( 1 )) true
(( 1 )) true
if (( 0 )) false
(( 0 )) false
echo "1<1"|bc true
echo "1<0"|bc true
TEST script:
printf 'if [ "1" ] '; if [ "1" ]; then echo true; else echo false; fi
printf ' [ "1" ] '; [ "1" ] && echo true || echo false
printf 'if [ "0" ] '; if [ "0" ]; then echo true; else echo false; fi
printf ' [ "0" ] '; [ "0" ] && echo true || echo false
echo
printf 'if [ 1 ] '; if [ 1 ]; then echo true; else echo false; fi
printf ' [ 1 ] '; [ 1 ] && echo true || echo false
printf 'if [ 0 ] '; if [ 0 ]; then echo true; else echo false; fi
printf ' [ 0 ] '; [ 0 ] && echo true || echo false
echo
printf 'if (( "1" )) '; if (("1")); then echo true; else echo false; fi
printf ' (( "1" )) '; (("1")) && echo true || echo false
printf 'if (( "0" )) '; if (("0")); then echo true; else echo false; fi
printf ' (( "0" )) '; (("0")) && echo true || echo false
echo
printf 'if (( 1 )) '; if (( 1 )); then echo true; else echo false; fi
printf ' (( 1 )) '; (( 1 )) && echo true || echo false
printf 'if (( 0 )) '; if (( 0 )); then echo true; else echo false; fi
printf ' (( 0 )) '; (( 0 )) && echo true || echo false
echo
printf 'echo "1<1"|bc '; echo "1<1"|bc >/dev/null && echo true || echo false
printf 'echo "1<0"|bc '; echo "1<0"|bc >/dev/null && echo true || echo false

Resources