Multiplicação e adição Bash

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

Olá, preciso de uma expressão simplificada para a terceira linha, talvez uma que precise não use substituição de comando.

Comentários

  • @Theophrastus: Como sugerido, funciona bem, mas e se eu quisesse usar expr em vez de (()) .
  • Isso é bash e não C, então remova todos os ; – a menos que você escreva em uma linha singular.
  • Veja também: unix.stackexchange.com/q/40786/117549
  • declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
  • À parte: $(( ... )) é expansão aritmética, não substituição de comando.

Resposta

Usando a expansão aritmética:

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

Usando o antiquado utilitário 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 um co-processo (age como uma espécie de serviço de computação em segundo plano¹):

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" 

Este último parece (possivelmente) 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 em que eu precisava processar uma grande quantidade de entrada uma volta. O processamento exigiu alguns cálculos de ponto flutuante, mas gerar bc algumas vezes no loop se mostrou extremamente lento. Sim, eu poderia ter resolvido de muitas outras maneiras, mas estava entediado …

Resposta

Você pode simplificar:

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

para:

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

Resposta

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

let a="2*k+1" 

Observe que não precisamos $k nesta estrutura; um simples k fará o trabalho.

Comentários

  • Isso falha se houver ' um arquivo sa chamado a=2whateverk+1 no atual Pior, se houver um ' arquivo sa chamado a=2+b[$(reboot)]k+1, isso chamará o comando reboot . O melhor é usar ((...)) aqui (((a = 2 * k + 1))) ou a sintaxe POSIX: a=$((2 * k + 1))
  • Podemos citá-lo; let a="2*k+1" para resolver isso.

Resposta

A expansão aritmética de 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 

for ((…)) loop

E, nesse caso, a expansão aritmética também poderia ser movido 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 a maneira mais curta de 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 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *