58
for k in {0..49};
do
a=$(($((2*$k))+1));
echo $a;
done

Hi, I need a simplified expression for the third line, maybe one that does not use command substitution.

6
  • @Theophrastus: As suggested it works fine but what if i wanted to use expr instead of (()).
    – AVS
    Jul 30, 2016 at 20:37
  • This is bash and not C, so remove all ; - unless you write it in a singular line.
    – ott--
    Jul 30, 2016 at 20:50
  • See also: unix.stackexchange.com/q/40786/117549
    – Jeff Schaller
    Jul 30, 2016 at 21:48
  • declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
    – Cyrus
    Jul 31, 2016 at 16:17
  • 2
    Aside: $(( ... )) is arithmetic expansion not command substitution. Oct 5, 2017 at 6:09

4 Answers 4

66

Using arithmetic expansion:

for (( k = 0; k < 50; ++k )); do
  a=$(( 2*k + 1 ))
  echo "$a"
done

Using the antiquated expr utility:

for (( k = 0; k < 50; ++k )); do
  a=$( expr 2 '*' "$k" + 1 )
  echo "$a"
done

Using bc -l (-l not actually needed in this case as no math functions are used):

for (( k = 0; k < 50; ++k )); do
  a=$( bc -l <<<"2*$k + 1" )
  echo "$a"
done

Using bc -l as a co-process (it acts like a sort of computation service in the background¹):

coproc bc -l

for (( k = 0; k < 50; ++k )); do
  printf "2*%d + 1\n" "$k" >&${COPROC[1]}
  read -u "${COPROC[0]}" a
  echo "$a"
done

kill "$COPROC_PID"

That last one looks (arguably) cleaner in ksh93:

bc -l |&
bc_pid="$!"

for (( k = 0; k < 50; ++k )); do
  print -p "2*$k + 1"
  read -p a
  print "$a"
done

kill "$bc_pid"

¹ This solved a an issue for me once where I needed to process a large amount of input in a loop. The processing required some floating point computations, but spawning bc a few times in the loop proved to be exceedingly slow. Yes, I could have solved it in many other ways, but I was bored...

0
26

You can simplify:

a=$(($((2*$k))+1));

to:

a=$((2*k+1))
5

You can use the let command to force a calculation.

let a="2*k+1"

Note that we don't need $k in this structure; a simple k will do the job.

2
  • 5
    That fails if there's a file called a=2whateverk+1 in the current directory. Worse, if there's a file called a=2+b[$(reboot)]k+1, that calls the reboot command. Best is to use ((...)) here (((a = 2 * k + 1))), or the POSIX syntax: a=$((2 * k + 1)) Jul 30, 2016 at 20:57
  • We can quote it; let a="2*k+1" to solve that. Jul 30, 2016 at 20:59
4

The arithmetic expansion you probably need is this:

a=$(( 1+2*k ))

In fact, you do not need to use a variable:

for k in {0..49}; do
    echo "$(( 1 + 2*k ))"
done

Or the counting variable could be moved to a for ((…)) loop:

for (( k=0;k<50;k++ )); do
    a=$(( 1+2*k ))
    printf '%s\n' "$a"
done

for ((…)) loop

And, in that case, the arithmetic expansion could also be moved to inside the for loop:

for (( k=0 ; a=1+2*k , k<50 ;  k++)); do
    printf '%s\n' "$a"
done

Or, to get all values in an array:

for (( k=0 ; a[k]=1+2*k , k<49 ;  k++ )); do :; done
printf '%s\n' "${a[@]}"

No formula

But probably the shortest way to avoid any arithmetic expansion is to increment a variable twice:

for (( k=0,a=1 ; k<50 ;  k++,a++,a++ )); do
    printf '%s\n' "$a"
done

Or, even simpler, just use seq:

seq 1 2 100

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .