Saya mencoba membuat skrip bash yang sangat sederhana untuk mendaftar semua kelipatan lima antara 375 dan 3500 (375, 380, 385 ...). Satu hal yang saya coba dan tidak berhasil adalah:
for i in {375..3500}
do
echo $i
(($i += 5))
done
Saya menyerah setelah beberapa saat dan menulis ini dalam BASIC dalam waktu sekitar 15 detik:
10 count = 375
20 print count
30 count = count+5
40 if count < 3500 then goto 20
Bagaimana saya bisa membuat program BASIC saya dalam skrip bash?
Jawaban:
Sebagai alternatif, gaya C tradisional untuk loop dapat digunakan:
Ini mungkin kurang jelas daripada menggunakan seq, tetapi tidak menelurkan subproses. Meskipun karena saya terbiasa dengan C, saya tidak akan kesulitan memahami ini, tapi YMMV.
sumber
dash
tidak mendukungnya. @ ChrisDown - Tidak ada alasan mengapa "POSIX sh" harus menyiratkan "no seq". Tapi ya, memang, saya telah mengabaikan fakta bahwa seq tidak ditentukan oleh POSIX.Karena Anda tetap menggunakan ekspansi brace, jadi manfaatkan fiturnya sepenuhnya:
Anda juga dapat menggunakan teknik ini untuk mencetak setiap angka dalam baris terpisah dengan teks opsional dengan menggunakan
printf
alih-alihecho
, misalnya:Edit
Seperti yang ditunjukkan oleh @kojiro dalam komentar Mac OS menggunakan bash 3 sebagai shell default, yang tidak mendukung peningkatan dalam ekspresi urutan ekspansi brace. Anda perlu memutakhirkan ke bash versi 4 atau menggunakan shell lain yang mendukungnya (mis. Zsh terbaru).
sumber
bash -c
cukup banyak jaminan bahwa dua shell berbeda terlibat. Apakah$SHELL --version
mengatakan itu bash 3?bash
fitur ini diperkenalkan. Saya sudah mempelajarinya sendiri dari komentar kojiro. Dan tolong jangan membandingkan saya dengan SC, saya benar-benar tidak tahu semua detail dan sejarah semua cangkang sejak akhir 1970. Sekali lagi - Jika Anda mengharapkan itu, harap harap downvote.Menggunakan SEQ (1)
Atau, cukup:
sumber
seq 375 5 3500
.Cuplikan for-loop Anda tidak berfungsi seperti yang Anda minta karena dua alasan:
(($i += 5))
- di sini$i
diperluas ke nilaii
. Dengan demikian ekspansi akan menjadi sesuatu seperti((375 += 5))
, yang tidak masuk akal (mencoba untuk menetapkan angka literal ke angka literal lain). Ini biasanya akan dicapai dengan((i += 5))
(tidak$
untuk memperluas variabel){375..3500}
akan diperluas sebelum iterasi pertama dari loop. Ini akan menjadi daftar angka375 376 ... 3499 3500
. Untuk setiap iterasi dari loop,i
akan ditugaskan ke masing-masing angka ini, satu-per-satu. Jadi pada awal setiap iterasi,i
akan dipindahkan ke nilai berikutnya dalam daftar itu, menghitung dalam langkah-langkah 1. Secara((i += 5))
efektif tidak melakukan apa-apa - ia menambahkan 5 ke i, tetapi kemudian saya baru saja ditugaskan lagi pada awal iterasi berikutnya.Saya pikir saya paling suka
for (( ; ; ))
jawabannya, tetapi berikut adalah beberapa alternatif untuk membuat Anda berpikir:Karena kita berurusan dengan kelipatan 5, dan
{a..b..i}
ekspansi tidak didukung di bash versi 3.2.57 (1) (di OS X), maka kita dapat melakukan hal yang agak misterius ini sebagai gantinya:Ini menunjukkan bagaimana bash dapat digunakan untuk membuat produk kartesius.
Saya pikir secara umum for for adalah cara yang paling nyaman untuk melakukan ini, tetapi jika Anda tertarik, Anda dapat menggunakan program while-loop (sedikit lebih dekat dengan BASIC Anda):
sumber
38
hingga349
. Yang kedua hanya dua angka:0
dan5
. Sekarang mari kita ciptakan pasang memerintahkan mereka semua kombinasi - Anda dapat menulis mereka sebagai set:{38,0}
,{38,5}
...{349,5}
, atau hanya menghapus simbol berlebihan{
,,
dan}
dan ... nomor baru380
...3495
.Meskipun ada, tentu saja, aplikasi untuk itu (
seq 375 5 3500
), ada berbagai cara untuk melakukan ini dari commandline. Meskipun yang tercepat dan paling sederhana hanya menggunakanseq
, berikut adalah beberapa opsi lain:sumber
$(($i % 5))
dapat ditulis$((i % 5))
.POSIXly:
...atau...
Saya tidak tahu mengapa Anda melakukannya dengan cara lain. Kecuali, tentu saja ...
... atau dengan
dc
:sumber
dc
kode ini bekerja. Ini tentu lebih menarik daripada menggunakanseq
.s
aves[
string]
ke atasp
array, kemudianl
membawanya kembali ke atas tumpukan danx
membuatnya sebagai makro. Dalam makro kami mendorong5
pada tumpukan kemudian pop itu dan yang kedua dari atas dan+
mereka, mengganti kedua nilai stack dengan jumlah mereka, yang dilubangip
dan di-d
upgrade sebelum3500
didorong pada stack, ketika kita pop dan dupe yang baru saja kita buat untuk perbandingan>
. Jika3500
lebih besar, kami memuat dan mengeksekusi sebagai makro string yang disimpan dalamp
array (makro kami saat ini) , atau jika tidak rusak.Jika Anda terjebak di Bash 3:
dan jika Anda lebih suka
awk
:Saya tidak tahu tentang ekspansi brace - itu benar-benar keren.
sumber