Multiplication et addition de Bash


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

Salut, j'ai besoin d'une expression simplifiée pour la troisième ligne, peut-être une qui n'utilise pas de substitution de commande.


@Theophrastus: Comme suggéré, cela fonctionne bien, mais si je voulais utiliser expr au lieu de (()).
AVS

Ce n'est bashpas le cas C, alors supprimez tout ;- sauf si vous l'écrivez sur une ligne singulière.
ott--


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

1
À part: $(( ... ))l'expansion arithmétique n'est pas une substitution de commande.
dave_thompson_085

Réponses:


27

Utilisation de l'expansion arithmétique:

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

Utilisation de l' exprutilitaire désuet :

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

Utilisation bc -l( -lpas réellement nécessaire dans ce cas car aucune fonction mathématique n'est utilisée):

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

Utilisé bc -lcomme un co-processus (il agit comme une sorte de service de calcul en arrière-plan¹):

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"

Ce dernier semble (sans doute) plus propre dans 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"

¹ Cela a résolu un problème pour moi une fois où je devais traiter une grande quantité d'entrée en boucle. Le traitement a nécessité quelques calculs en virgule flottante, mais le frai bcplusieurs fois dans la boucle s'est avéré extrêmement lent. Oui, j'aurais pu le résoudre de bien d'autres façons, mais je m'ennuyais ...



5

Vous pouvez utiliser la letcommande pour forcer un calcul.

let a="2*k+1"

Notez que nous n'avons pas besoin $kde cette structure; un simple kfera le travail.


4
Cela échoue s'il y a un fichier appelé a=2whateverk+1dans le répertoire courant. Pire, s'il y a un fichier appelé a=2+b[$(reboot)]k+1, qui appelle la rebootcommande. Le mieux est d'utiliser ((...))ici ( ((a = 2 * k + 1))), ou la syntaxe POSIX:a=$((2 * k + 1))
Stéphane Chazelas

Nous pouvons le citer; let a="2*k+1"pour résoudre ça.
Stephen Harris

2

L'expansion arithmétique dont vous avez probablement besoin est la suivante:

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

En fait, vous n'avez pas besoin d'utiliser une variable:

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

Ou la variable de comptage pourrait être déplacée dans une for ((…))boucle:

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

pour ((…)) boucle

Et, dans ce cas, l'expansion arithmétique pourrait également être déplacée à l'intérieur de la boucle for:

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

Ou, pour obtenir toutes les valeurs d'un tableau:

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

Pas de formule

Mais probablement le moyen le plus court d'éviter toute expansion arithmétique est d'incrémenter une variable deux fois:

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

Ou, encore plus simple, utilisez simplement seq:

seq 1 2 100
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.