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

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

Using arithmetic expansion:

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

Using expr:

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

  • good exaple coprocess code. :) – Jasen Jul 31 '16 at 0:29
8

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.

  • 4
    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)) – Stéphane Chazelas Jul 30 '16 at 20:57
  • We can quote it; let a="2*k+1" to solve that. – Stephen Harris Jul 30 '16 at 20:59
1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.