Anda dapat membandingkan hanya dua angka dengan dcseperti:
dc -e "[$1]sM $2d $1<Mp"
... di mana "$1"nilai maksimum Anda dan "$2"merupakan angka yang akan Anda cetak jika lebih rendah dari itu "$1". Itu juga membutuhkan GNU dc- tetapi Anda dapat melakukan hal yang sama dengan mudah seperti:
dc <<MAX
[$1]sM $2d $1<Mp
MAX
Dalam kedua kasus di atas Anda dapat mengatur presisi ke sesuatu selain 0 (default) seperti ${desired_precision}k. Untuk keduanya, Anda juga harus memastikan bahwa kedua nilai tersebut merupakan angka pasti karena dcdapat membuat system()panggilan dengan !operator.
Dengan skrip kecil berikut (dan selanjutnya) Anda harus memverifikasi input juga - suka grep -v \!|dcatau sesuatu untuk menangani input sewenang - wenang. Anda juga harus tahu bahwa dcmenafsirkan angka negatif dengan _awalan daripada -awalan - karena yang terakhir adalah operator pengurangan.
Selain itu, dengan skrip ini dcakan terbaca \nnomor ewline terpisah berurutan sebanyak yang Anda mau berikan, dan cetak untuk setiap $maxnilai atau input Anda, tergantung mana yang lebih rendah dari wo:
dc -e "${max}sm
[ z 0=? d lm<M p s0 lTx ]ST
[ ? z 0!=T q ]S?
[ s0 lm ]SM lTx"
Jadi ... masing-masing [persegi kurung ]hamparan adalah dc string yang objek yang Saved masing-masing untuk array yang masing-masing - salah satu dari T, ?atau M. Selain beberapa hal lain yang dcmungkin dilakukan dengan sebuah string , ia juga dapat menjadikannya xsebagai makro. Jika Anda mengaturnya dengan benar, dcskrip kecil yang berfungsi penuh dirakit cukup sederhana.
dcbekerja pada tumpukan . Semua objek input ditumpuk masing-masing pada yang terakhir - setiap objek input baru mendorong objek teratas terakhir dan semua objek di bawahnya di atas tumpukan dengan satu saat ditambahkan. Sebagian besar referensi ke objek adalah ke nilai tumpukan teratas, dan sebagian besar referensi muncul di atas tumpukan (yang menarik semua objek di bawahnya satu per satu) .
Selain tumpukan utama, ada juga (setidaknya) 256 array dan masing-masing elemen array memiliki tumpukan sendiri. Saya tidak banyak menggunakan itu di sini. Saya hanya menyimpan string seperti yang disebutkan sehingga saya dapat menggunakannya lketika diinginkan dan membuat xmereka kondisional, dan saya smerobek $maxnilai di bagian atas marray.
Bagaimanapun, sedikit ini dctidak, sebagian besar, apa yang dilakukan oleh shell-script Anda. Itu memang menggunakan opsi GNU-isme -e- seperti dcumumnya mengambil parameternya dari standard-in - tetapi Anda bisa melakukan hal yang sama seperti:
echo "$script" | cat - /dev/tty | dc
... jika $scripttampak seperti bit di atas.
Ini berfungsi seperti:
lTx- Ini loads dan e xecutes makro disimpan di bagian atas T (untuk tes, saya kira - Saya biasanya mengambil nama-nama sewenang-wenang) .
z 0=?- Test kemudian menguji kedalaman tumpukan dengan zdan, jika tumpukan kosong (baca: menampung 0 objek) ia memanggil ?makro.
? z0!=T q- ?Makro dinamai untuk ? dcperintah builtin yang membaca baris input dari stdin, tapi saya juga menambahkan ztes kedalaman tumpukan lain untuk itu, sehingga dapat cocok qdengan seluruh program kecil jika menarik garis kosong atau menekan EOF. Tetapi jika !tidak dan malah berhasil mengisi stack, ia memanggil Test lagi.
d lm<M- Test kemudian akan dmenggandakan bagian atas tumpukan dan membandingkannya dengan $max (seperti yang disimpan di m) . Jika mnilainya lebih rendah, dcpanggil Mmakro.
s0 lm- MHanya muncul bagian atas tumpukan dan membuangnya ke skalar dummy 0- hanya cara murah untuk muncul tumpukan. Hal ini juga loads mlagi sebelum kembali ke Test.
p- Ini berarti bahwa jika mkurang dari puncak tumpukan saat ini, maka mganti itu (bagian datasnya, bagaimanapun) dan di sini di- pbengkokkan, yang lain tidak dan apa pun input yang di- pbengkokkan sebagai gantinya.
s0- Setelah itu (karena ptidak memunculkan tumpukan) kami membuang bagian atas tumpukan 0lagi, dan kemudian ...
lTx- rekursif load Test sekali lagi maka e xecute lagi.
Jadi, Anda dapat menjalankan potongan kecil ini dan mengetik nomor secara interaktif di terminal Anda dan dcakan mencetak kembali pada Anda nomor yang Anda masukkan atau nilai $maxjika nomor yang Anda ketikkan lebih besar. Itu juga akan menerima file apa pun (seperti pipa) sebagai input standar. Ini akan melanjutkan loop baca / bandingkan / cetak sampai bertemu dengan garis kosong atau EOF.
Beberapa catatan tentang ini - saya menulis ini hanya untuk meniru perilaku dalam fungsi shell Anda, sehingga hanya menangani satu angka per baris dengan kuat. dcnamun, dapat menangani sebanyak mungkin angka yang dipisahkan spasi per baris seperti yang Anda inginkan. Namun , karena tumpukannya, angka terakhir pada sebuah garis akhirnya menjadi yang pertama beroperasi, dan, seperti yang tertulis, dcakan mencetak hasilnya secara terbalik jika Anda mencetak / mengetik lebih dari satu angka per baris di dalamnya. Cara yang tepat untuk mengatasinya adalah dengan menyimpan sebuah baris dalam sebuah array, kemudian mengerjakannya.
Seperti ini:
dc -e "${max}sm
[ d lm<M la 1+ d sa :a z0!=A ]SA
[ la d ;ap s0 1- d sa 0!=P ]SP
[ ? z 0=q lAx lPx l?x ]S?
[q]Sq [ s0 lm ]SM 0sa l?x"
Tapi ... Saya tidak tahu apakah saya ingin menjelaskannya secara mendalam. Cukuplah untuk mengatakan bahwa ketika dcdibaca di setiap nilai pada stack ia menyimpan nilai atau $maxnilainya dalam array yang diindeks, dan, begitu ia mendeteksi stack sekali lagi kosong, ia kemudian mencetak setiap objek yang diindeks sebelum mencoba membaca yang lain jalur input.
Jadi, sementara skrip pertama tidak ...
10 15 20 25 30 ##my input line
20
20
20
15
10 ##see what I mean?
Yang kedua tidak:
10 15 20 25 30 ##my input line
10 ##that's better
15
20
20 ##$max is 20 for both examples
20
Anda dapat menangani float dengan presisi sewenang-wenang jika Anda pertama kali mengaturnya dengan kperintah. Dan Anda dapat mengubah input atau radisi output secara independen - yang kadang-kadang bisa berguna karena alasan yang mungkin tidak Anda harapkan. Sebagai contoh:
echo 100000o 10p|dc
00010
... yang pertama mengatur dcoutput radix ke 100000 kemudian mencetak 10.