Множення та складання башів


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

Привіт, мені потрібен спрощений вираз для третього рядка, можливо, той, який не використовує підстановку команд.


@Theophrastus: Як було запропоновано, він працює добре, але що робити, якщо я хотів використовувати expr замість (()).
AVS

Це є, bashа ні C, тому видаліть усі ;- якщо ви не запишете це в однині рядка.
ott--


declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
Сайрус

1
Убік: $(( ... ))арифметичне розширення не є підстановкою команд.
dave_thompson_085

Відповіді:


28

Використання арифметичного розширення:

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

Використання застарілої exprутиліти:

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

Використання bc -l( -lфактично не потрібне в цьому випадку, оскільки не використовуються математичні функції):

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

Використання bc -lяк спільного процесу (він виступає як свого роду обчислювальна служба у фоновому режимі¹):

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"

Останній виглядає (мабуть) чистішим у 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"

¹ Це колись вирішило для мене проблему, коли мені потрібно було обробити велику кількість вводу в циклі. Обробка вимагала деяких обчислень з плаваючою точкою, але нерест bcу циклі кілька разів виявився надзвичайно повільним. Так, я міг би вирішити це багатьма іншими способами, але мені було нудно ...



5

Ви можете використовувати letкоманду для примусового обчислення.

let a="2*k+1"

Зауважте, що нам не потрібно $kв цій структурі; простий kзробить роботу.


4
Це не вдається, якщо a=2whateverk+1в поточному каталозі є файл, який викликається . Гірше, якщо є файл a=2+b[$(reboot)]k+1, який називається , який викликає rebootкоманду. Найкраще використовувати ((...))тут ( ((a = 2 * k + 1))) або синтаксис POSIX:a=$((2 * k + 1))
Stéphane Chazelas

Ми можемо це процитувати; let a="2*k+1"щоб вирішити це.
Стівен Харріс

2

Арифметичне розширення, яке вам, мабуть, потрібно, це:

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

Насправді, вам не потрібно використовувати змінну:

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

Або змінну підрахунку можна перемістити до for ((…))циклу:

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

для ((…)) петлі

І в цьому випадку арифметичне розширення також може бути переміщене всередину циклу for:

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

Або, щоб отримати всі значення в масиві:

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

Формули немає

Але, мабуть, найкоротший спосіб уникнути арифметичного розширення - збільшити зміну в два рази:

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

Або, що ще простіше, просто використовуйте seq:

seq 1 2 100
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.