Increment variable value by 1 (shell programming) - shell

I can't seem to be able to increase the variable value by 1. I have looked at tutorialspoint's Unix / Linux Shell Programming tutorial but it only shows how to add together two variables.
I have tried the following methods but they don't work:
i=0
$i=$i+1 # doesn't work: command not found
echo "$i"
$i='expr $i+1' # doesn't work: command not found
echo "$i"
$i++ # doesn't work*, command not found
echo "$i"
How do I increment the value of a variable by 1?

You can use an arithmetic expansion like so:
i=$((i+1))
or declare i as an integer variable and use the += operator for incrementing its value.
declare -i i=0
i+=1
or use the (( construct.
((i++))

The way to use expr:
i=0
i=`expr $i + 1`
The way to use i++ (unless you're running with -e/-o errexit):
((i++)); echo $i;
Tested in gnu bash.

you can use bc as it can also do floats
var=$(echo "1+2"|bc)

These are the methods I know:
ichramm#NOTPARALLEL ~$ i=10; echo $i;
10
ichramm#NOTPARALLEL ~$ ((i+=1)); echo $i;
11
ichramm#NOTPARALLEL ~$ ((i=i+1)); echo $i;
12
ichramm#NOTPARALLEL ~$ i=`expr $i + 1`; echo $i;
13
Note the spaces in the last example, also note that's the only one that uses $i.

Related

Sum of integer variables bash script

How can I do the sum of integers with bash script I read some variables with a for and I need to do the sum.
I have written the code like this:
Read N
Sum=0
for ((i=1;i<=N;i++))
do
read number
sum=sum+number
done
echo $sum
Use the arithmetic command ((...)):
#! /bin/bash
read n
sum=0
for ((i=1; i<=n; i++)) ; do
read number
((sum+=number))
done
echo $sum
#!/bin/bash
echo "Enter number:"
read N
re='^[0-9]+$'
if ! [[ ${N} =~ ${re} ]]
then
echo "Error. It's not a number"
exit 1
fi
Sum=0
for ((i=1;i<=N;i++))
do
sum=$((${sum} + ${i}))
done
echo "${sum}"
Well, not a straight bash solution, but you can also use seq and datamash (https://www.gnu.org/software/datamash/):
#!/bin/bash
read N
seq 1 $N | datamash sum 1
It is really simple (and it has its limitations), but it works. You can use other options on seq for increments different than 1 and so on.
It is also possible to declare a variable as an integer with declare -i. Any assignment to that variable is then evaluated as an arithmetic expression:
#!/bin/bash
declare -i sum=0
read -p "Enter n: " n
for ((i=1; i<=n; i++)) ; do
read -p "Enter number #$i: " number
sum+=number #sum=sum+number would also work
done
echo "Sum: $sum"
See Bash Reference Manual for more information. Using arithmetic command ((...)) is preferred, see choroba's answer.
$ declare -i var1=1
$ var2=1
$ var1+=5
$ echo "$var1"
6
$ var2+=5
$ echo "$var2"
15
This can be a tad confusing as += behaves differently depending on the variable's attributes. It's therefore better to explicitly use ((...)) for arithmetic operations.

Assign variables inside for loops

I am trying a small code which is
for(( i =0;i<2;i++ )); do p$i=\"pra$i\"; done
expected output is:
Variable must be assigned
p0="pra0"
p1="pra1"
But bash is taking that as command and am getting output as
p0="pra0": command not found
p1="pra1": command not found
Thanks
Use eval to have the value evaluated and stored as you want:
$ for(( i =0;i<2;i++ )); do eval p$i=\"pra$i\"; done
$ echo $p1
pra1
Or better with declare (thanks chepner as always!):
$ for(( i =0;i<2;i++ )); do declare "p$i=pra$i"; done
$ echo $p1
pra1
for (( i =0;i<2;i++ )); do
printf -v "p$i" '%s' "pra$i"
done

Loop in UNIX is not working

Please tell me what is wrong with the UNIX code below.
#!/bin/ksh
p=10
for i in $p
do
echo $i
done
i am expecting output as
1
2
3
.
.
.
but the output am getting is just 10
I need for loop not while loop.
in ksh
#!/bin/ksh
p=10
i=1
while ((i<=p)); do
echo $i
i=$((i+1))
done
or
#!/bin/ksh
# with for you can only do this
for i in 1 2 3 4 5 6 7 8 9 10; do
echo $i
done
in bash it works as expected
#!/bin/bash
p=10
for (( i=1; i<=p; i++ )); do
echo $i
done
there is a Linux command seqthat can be used for both ksh and bash. But it is a Linux command. So this will not work on Solaris or other Unix systems that don't have the progrtam seq installed.
# on Linux, bash or ksh
p=10
for i in $(seq $p); do
echo $i
done
The following uses only shell built-ins and therefore will work for all bash installations (e.g. on Solaris) but not for ksh
#!/bin/bash
p=10
for i in `eval echo {1..$p}`; do
echo $i
done
This complicated construct is necessary because of brace expansion occurrs before variable expansion
You have to assign a range. Otherwise the loop can't work. This should do it:
#!/bin/ksh
p=10
for i in {0..$p}
do
echo $i
done
#fedorqui: You are right, I absolutely missed that. When I do stuff like this in Bash (I don't know if it's the same for KornShell), I go like:
for ((i=0; i<$p; i++))
in UNIX KSH
#!/bin/ksh
while [ ${i:=1} -le 10 ]
do
echo "$i"
let i+=1
done

{$a..3} does not expand right in shell script

Why the output is {1..3} rather than 123 ?
#!/bin/sh
a=1
for i in {$a..3}
do
echo -n $i
done
If I change {$a..3} to $(echo {$a..3}), it does not work either.
Brace expansion is performed before parameter substitution. But since that isn't a valid brace expansion, it isn't expanded. Use seq instead.
Ignacio's answer is right.
Here are some other solutions!
You can use a c-style for-loop in bash:
for (( i=a; i<=3; i++ ))
Or you can use dangerous eval, but you have to be sure that $a variable can't be anything else but a number, especially if the user is able to change it:
for i in $(echo eval {$a..3})
Or while loop with a variable in pure sh:
i=$a
while [ "$i" -le 3 ]
do
echo -n $i
i=$(( i + 1 ))
done

Sequence expression in bash

I'm used to used the following feature of bash :
for i in ${1..23} ; do echo $i ; done
This doesn't generalize. For instance, replacing 23 by even $p does not work. As the documentation says, this is a purely syntactic feature.
What would you replace this with ?
Note : Of course, this could be done using a while and an auxiliary variable, but this is not what i'm looking for, even if it works. I'm failing back to this actually.
You could use the seq tool to achieve the effect, I don't know if that's okay for your use case
~$ P=3 && for i in `seq 1 $P`; do echo $i; done
1
2
3
or litb's suggestion
~$ P=3 && for ((i=1;i<=$P;i++)); do echo $i; done
1
2
3
If you have it available, the seq command can do similar. Your example might then be:
p=23
for i in `seq 1 $p`
do
echo $i
done
On linux, there is a seq command (unfortunately it's missing in OS X).
#!/bin/bash
p=23
for i in `seq 1 $p`;
do
echo $i
done
OS X workaround: http://scruss.com/blog/2008/02/08/seq-for-os-x/comment-page-1/
$ p=18
$ a='{1..$p}'
$ for num in $( eval echo $(eval echo $a) ); do echo $num; done

Resources