Multiplicação e adição de bash

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

Oi, eu preciso de uma expressão simplificada para a terceira linha, talvez uma que não use substituição de comandos.

    
por AVS 30.07.2016 / 22:31

4 respostas

13

Usando expansão aritmética:

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

Usando expr :

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

Usando bc -l ( -l não é realmente necessário neste caso, pois nenhuma função matemática é usada):

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

Usando bc -l como co-processo (age como uma espécie de serviço de computação no plano de fundo¹):

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"

Esse último parece (sem dúvida) mais limpo em 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"

¹ Isso resolveu um problema para mim uma vez em que precisei processar uma grande quantidade de entrada em um loop. O processamento exigia alguns cálculos de ponto flutuante, mas gerar bc algumas vezes no loop mostrou-se extremamente lento. Sim, eu poderia ter resolvido isso de muitas outras maneiras, mas eu estava entediado ...

    
por 30.07.2016 / 23:23
5

Você pode simplificar:

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

para:

a=$((2*k+1))
    
por 30.07.2016 / 23:01
3

Você pode usar o comando let para forçar um cálculo.

let a="2*k+1"

Note que não precisamos de $k nessa estrutura; um simples k fará o trabalho.

    
por 30.07.2016 / 22:41
1

A expansão aritmética que você provavelmente precisa é esta:

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

Na verdade, você não precisa usar uma variável:

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

Ou a variável de contagem pode ser movida para um for ((…)) loop:

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

para loop ((…))

E, nesse caso, a expansão aritmética também pode ser movida para dentro do loop for:

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

Ou para obter todos os valores em uma matriz:

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

Sem fórmula

Mas provavelmente o caminho mais curto para evitar qualquer expansão aritmética é incrementar uma variável duas vezes:

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

Ou, ainda mais simples, use seq:

seq 1 2 100
    
por 31.07.2016 / 21:17