Moltiplicazione e aggiunta di Bash


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

Ciao, ho bisogno di un'espressione semplificata per la terza riga, forse una che non usa la sostituzione dei comandi.


@Theophrastus: Come suggerito, funziona bene, ma se volessi usare expr invece di (()).
AVS,

Questo è bashe non C, quindi rimuovi tutto ;, a meno che tu non lo scriva in una riga singolare.
ott--


declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
Ciro,

1
A parte: $(( ... ))l'espansione aritmetica non sostituisce i comandi.
dave_thompson_085,

Risposte:


27

Utilizzando l'espansione aritmetica:

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

Utilizzando l' exprutilità antiquata :

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

Utilizzo bc -l( -lnon effettivamente necessario in questo caso poiché non vengono utilizzate funzioni matematiche):

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

Usando bc -lcome co-processo (si comporta come una sorta di servizio di calcolo in 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"

Quest'ultimo sembra (probabilmente) più pulito 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"

¹ Ciò ha risolto un problema per me una volta in cui avevo bisogno di elaborare una grande quantità di input in un ciclo. L'elaborazione ha richiesto alcuni calcoli in virgola mobile, ma la generazione di bcalcune volte nel loop si è rivelata estremamente lenta. Sì, avrei potuto risolverlo in molti altri modi, ma ero annoiato ...



5

È possibile utilizzare il letcomando per forzare un calcolo.

let a="2*k+1"

Si noti che non è necessario $kin questa struttura; un semplice kfarà il lavoro.


4
Ciò fallisce se c'è un file chiamato a=2whateverk+1nella directory corrente. Peggio ancora, se c'è un file chiamato a=2+b[$(reboot)]k+1, che chiama il rebootcomando. La cosa migliore è usare ((...))qui ( ((a = 2 * k + 1))) o la sintassi POSIX:a=$((2 * k + 1))
Stéphane Chazelas,

Possiamo citarlo; let a="2*k+1"per risolverlo.
Stephen Harris,

2

L'espansione aritmetica di cui probabilmente hai bisogno è questa:

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

In effetti, non è necessario utilizzare una variabile:

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

Oppure la variabile di conteggio potrebbe essere spostata in un for ((…))ciclo:

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

per il ciclo ((…))

E, in tal caso, l'espansione aritmetica potrebbe anche essere spostata all'interno del ciclo for:

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

Oppure, per ottenere tutti i valori in un array:

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

Nessuna formula

Ma probabilmente il modo più breve per evitare qualsiasi espansione aritmetica è incrementare una variabile due volte:

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

O, ancora più semplice, basta usare seq:

seq 1 2 100
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.