I have to a perform logic like this.
I have a array.
expression for this in shell
[(first no + arrlen) - ( index +1 ) - ge 10 ]
I have code this like this but it's not working
#!/bin/bash
array=(4 5 6 7 8 9)
for i in ${array[#]}
do
echo $i
done
echo "${#array[#]}"
l=${#array[#]}
count=0
for (( i=0; i < ${#array[#]}; i++ ))
do
if [ ($(`expr $i + $l`) - $(`expr ${!array[#]} + 1`)) -ge 10 ]
then
count=`expr $count + 1`
else
echo
fi
done
Your code could look like this:
#!/bin/bash
array=(4 5 6 7 8 9)
for i in "${array[#]}"; do
echo "$i"
done
length=${#array[#]}
first=${array[0]}
count=0
for (( i=0; i < length; i++ )); do
if (( (first + length) - (i + 1) >= 10 )); then
((count++))
else
echo "something"
fi
done
Don't use expr, use (( )) for arithmetic expressions
Quote expansions: "$i", "${array[#]}", ...
${!array[#]} expands to ALL indexes of your array, not the current index
Related
I am trying to make Linux bash for my study homework and I think everything is fine(checked many resources), but still error is showing up (–eq: binary operator expected ). What's wrong in my example?
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
tot=$(expr $i + $j)
echo „tot value: $tot”
tmp=$(expr $tot % 2)
echo „tmp value: $tmp”
if [ $tmp –eq 0 ]; then
echo –e –n „\033[47m ”
else
echo –e –n „\033[40m”
fi
done
echo –e –n „\033[40m” #### set back background colour to black
echo „” #### print the new line ####
done
You are using the wrong character in –eq. It should be a minus (-), not a hyphen (–). The same goes for the hyphen you use on the echo lines.
Also consider using bash's built-in arithmetic expansion instead of expr and test:
#!/bin/bash
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
(( tot = i + j ))
echo "tot value: $tot"
(( tmp = tot % 2 ))
echo "tmp value: $tmp"
if (( tmp == 0 )); then
echo -e -n "\033[47m "
else
echo -e -n "\033[40m"
fi
done
echo -e "\033[40m" #### set back background colour to black
done
I am trying to print the multiplication table from 1 to 10 in shell. However, my output is only printing it for 1.
My current implementation is
i=1
j=1
while [ $i -le 10 ]
do
while [ $j -le 10 ]
do
echo " $i x $j = `expr $i \* $j`"
j=`expr $j + 1`
done
i=`expr $i + 1`
done
Just move the initialization of j inside the while loop. After completion of the first loop, your variable j has the value as 10. So for the second iteration of the outer loop, it's not entering the inner loop since it's value is 10.
i=1
while [ $i -le 10 ]
do
j=1
while [ $j -le 10 ]
do
echo " $i x $j = `expr $i \* $j`"
j=`expr $j + 1`
done
i=`expr $i + 1`
done
I'd like to know how to print Fibonacci series using recursion in bash with only 1 variable.
From what I've done:
fib()
{
i=$1
if (( $i <= 1 ))
then echo 0
elif (( $i == 2 ))
then echo 1
else
echo $(( $(fib $(($i - 1)) ) + $(fib $(($i - 2)) ) ))
fi
}
echo $(fib $1)
I get the correct output of the final iteration, for example if I enter 10 I will get 34, but I'd like to print the whole sequence of numbers, i.e. all the iterations as well. How can I achieve that?
Another way I tried was by:
#!/bin/bash
arr[0]=0
arr[1]=1
for (( i=0; i<=10; i++ ))
do
echo -n "${arr[0]} "
arr[0]=$((${arr[0]} + ${arr[1]} ))
arr[1]=$((${arr[0]} - ${arr[1]} ))
done
echo ""
But obviously here I've used a for loop, but I don't want to use another variable.
Just for (my kind of) fun, this code prints the Fibonacci numbers from the 0th to the 92nd (as defined in Fibonacci number - Wikipedia) with a recursive function that uses no variables:
#! /bin/bash
function fib
{
echo ${3-0}
(($1 > 0)) && fib $(($1-1)) ${3-0} $((${2-1}+${3-0}))
}
fib 92
Some may claim that using the positional parameters ($1, $2, $3) for this is cheating, but then other solutions could be said to be using two variables ($i and $1).
The code takes under 0.01 seconds to run on my (oldish) Linux machine.
The code should work with numbers up to 92 with Bash version 3 or later on any platform. See Bash Number Limit?. Numbers higher than 93 will cause to code to produce garbage results due to arithmetic overflow.
Variables in bash are global by default. You need to make i local explicitly.
fib () {
local i
i=$1
if (( i <= 1 )); then
echo $i
else
echo $(( $(fib $((i-1)) ) + $(fib $((i - 2)) ) ))
fi
}
(Also, your base cases are a little off if you are starting with 0, and 2 need not be a base case; fib 2 can be derived from the base cases fib 0 and fib 1.)
If you want to print each fibonacci value from 1 to $n, I suggest:
fib_r() {
local i=$1
if (( i < 0 )); then
echo "Error: negative numbers not allowed" >&2
exit 1
elif (( i <= 1 )); then
echo $i
else
echo $(( $($FUNCNAME $((i - 1)) ) + $($FUNCNAME $((i - 2)) ) ))
fi
}
fib() {
local i
for (( i = 1; i <= $1; i++ )); do
fib_r $i
done
}
fib 10
outputs
0
1
1
2
3
5
8
13
21
34
It's still one variable, albeit one per function.
I use the bash variable $FUNCNAME in the recursive function so you don't have to hardcode the function name within itself. I got bit by not updating that line when I renamed the function.
Of course your performance will greatly improve if you cache the results: "fib 16" takes, on my VM, about 3.5 sec without caching and about 0.03 sec with caching.
fib_r() {
local i=$1
if (( i < 0 )); then
echo "Error: negative numbers not allowed" >&2
exit 1
elif [[ -n ${fib_cache[i]} ]]; then
echo "${fib_cache[i]}"
elif (( i <= 1 )); then
echo $i
else
echo $(( $( $FUNCNAME $((i - 1)) ) + $( $FUNCNAME $((i - 2)) ) ))
fi
}
fib_cache=()
fib() {
local i
for ((i=1; i<=$1; i++)); do
fib_cache[i]=$(fib_r $i)
echo "${fib_cache[i]}"
done
}
This question already has an answer here:
Shell Script: Hexadecimal Loop
(1 answer)
Closed 6 years ago.
I want a bash script to print list of incremental MAC addresses. This is the while loop I'm using:
i=1
j=1
k=1
while [ $i -le 5 ]; do
j=1
while [ $j -le 46 ]; do
k=1
while [ $k -le 44 ]; do
echo "mac=00:00:01:$i:$j:$k"
k=`expr $k + 1`
done
j=`expr $j + 1`
done
i=`expr $i + 1`
done
I want the MACs to print in hexadecimal. So I want this -
00:00:01:01:09:09
to increment to this -
00:00:01:01:09:0a
and NOT to this -
00:00:01:01:09:10
Look at printf builtin bash command, and change your echo with
printf "mac=00:00:01:%2.2x:%2.2x:%2.2x\n" $i $j $k
i=1
j=1
k=1
# using for loop instead of while loop
for i in $(seq 1 5); do
j=1
for j in $(seq 1 46); do
k=1
for k in $(seq 1 44); do
echo "mac=00:00:01:$i:$j:$k"
#using following command for HEX increment.
k=`echo "obase=ibase=16;${k}+1"`
done
j=`echo "obase=ibase=16;${j}+1"`
done
i=`echo "obase=ibase=16;${i}+1"`
done
Have some function with loop:
runcfg () {
o=0
while (( o<3 )); do
echo $o
(( o++ ))
done
}
It calls from another script manager.sh by:
...
-C|--runconfig)
source $APP_BASEDIR/app-install/bin/config_functions; runcfg;
shift;;
...
Let's run it:
$ bash -x manager.sh -run
And look at output:
...
+ runcfg
+ o=0
+ (( o<3 ))
+ echo 0
0
+ (( o++ ))
That's all lines... Nothing else happens.
But! If make little chage and add && after arithmetic call:
runcfg () {
o=0
while (( o<3 )); do
echo $o
(( o++ )) && echo ++OK || echo ++ER
done
}
It works!
...
+ runcfg
+ o=0
+ (( o<3 ))
+ echo 0
0
+ (( o++ ))
+ echo ++ER
++ER
+ (( o<3 ))
+ echo 1
1
+ (( o++ ))
+ echo ++OK
++OK
+ (( o<3 ))
+ echo 2
2
+ (( o++ ))
+ echo ++OK
++OK
+ (( o<3 ))
+ shift
...
What is this?
Your script is configured to exit on error (note that it prints ++ER the first time), and ((o++)) == ((0)), which returns 1 (an error). Options:
Use let o++ instead.
Ignore the error (((o++))||:)
Use a for loop (for ((o = 0; o < 3; o++)))
Turn off exit-on-error (set +e).