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.

Best Answer


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...