Penggandaan dan penambahan bash


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

Hai, saya perlu ungkapan yang disederhanakan untuk baris ketiga, mungkin yang tidak menggunakan substitusi perintah.


@Theophrastus: Seperti yang disarankan berfungsi dengan baik tetapi bagaimana jika saya ingin menggunakan expr bukannya (()).
AVS

Ini bashdan tidak C, jadi hapus semua ;- kecuali Anda menulisnya dalam satu baris.
ott--


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

1
Selain itu: $(( ... ))apakah ekspansi aritmatika bukan perintah substitusi.
dave_thompson_085

Jawaban:


27

Menggunakan ekspansi aritmatika:

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

Menggunakan exprutilitas kuno :

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

Menggunakan bc -l( -lsebenarnya tidak diperlukan dalam kasus ini karena tidak ada fungsi matematika yang digunakan):

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

Menggunakan bc -lsebagai proses bersama (ini bertindak seperti semacam layanan perhitungan di latar belakang¹):

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"

Yang terakhir terlihat (bisa dibilang) lebih bersih di 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"

¹ Ini pernah memecahkan masalah bagi saya ketika saya harus memproses sejumlah besar input dalam satu lingkaran. Pemrosesan membutuhkan beberapa perhitungan floating point, tetapi pemijahan bcbeberapa kali dalam loop terbukti sangat lambat. Ya, saya bisa menyelesaikannya dengan banyak cara lain, tetapi saya bosan ...



5

Anda dapat menggunakan letperintah untuk memaksa perhitungan.

let a="2*k+1"

Perhatikan bahwa kita tidak perlu $kdalam struktur ini; sederhana kakan melakukan pekerjaan itu.


4
Itu gagal jika ada file yang dipanggil a=2whateverk+1di direktori saat ini. Lebih buruk lagi, jika ada file yang dipanggil a=2+b[$(reboot)]k+1, yang memanggil rebootperintah. Yang terbaik adalah menggunakan di ((...))sini ( ((a = 2 * k + 1))), atau sintaks POSIX:a=$((2 * k + 1))
Stéphane Chazelas

Kami bisa mengutipnya; let a="2*k+1"untuk menyelesaikannya.
Stephen Harris

2

Perluasan aritmatika yang mungkin Anda butuhkan adalah ini:

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

Bahkan, Anda tidak perlu menggunakan variabel:

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

Atau variabel penghitungan dapat dipindahkan ke for ((…))loop:

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

untuk ((...)) loop

Dan, dalam hal itu, ekspansi aritmatika juga dapat dipindahkan ke dalam loop for:

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

Atau, untuk mendapatkan semua nilai dalam array:

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

Tidak ada formula

Tapi mungkin cara terpendek untuk menghindari ekspansi aritmatika adalah dengan menambahkan variabel dua kali:

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

Atau, lebih sederhana, cukup gunakan seq:

seq 1 2 100
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.