Script Anda menggunakan tiga fitur shell Bash yang tidak disediakan oleh semua shell bergaya Bourne. Seperti yang dikatakan heemayl , Anda bisa menjalankan skrip itu dengan bashalih - alih sh. Baris hashbang Anda di atas ( #!/bin/bash) menentukan bashtetapi hanya efektif jika Anda menjalankan skrip, seperti yang dijelaskan heemayl . Jika Anda meneruskan nama skrip ke sh, shtidak akan secara otomatis memanggil bash, tetapi hanya akan menjalankan skrip. Ini karena begitu skrip Anda benar-benar berjalan, garis hashbang tidak berpengaruh .
Alternatif Anda yang lain, jika Anda perlu menulis skrip yang sepenuhnya portabel yang tidak bergantung pada fitur Bash, adalah mengubah skrip Anda agar berfungsi tanpa mereka. Fitur Bash yang Anda gunakan adalah:
- Sebuah Array . Ini yang lebih dulu, jadi inilah yang menghasilkan kesalahan ketika Anda mencoba menjalankan skrip Anda dengan shell Dash . Ekspresi kurung
( {a..z} ), yang Anda tetapkan untuk chars, menciptakan array, dan ${chars[i]}, yang muncul di loop Anda, indeks ke dalamnya.
- Ekspansi penjepit. Di Bash, dan juga di banyak kerang lainnya,
{a..z}diperluas ke a b c d e f g h i j k l m n o p q r s t u v w x y z. Namun, ini bukan fitur universal (atau standar) dari shell Bourne-style, dan Dash tidak mendukungnya.
- Sintaks -loop pengganti
for -gaya-C . Meskipun didasarkan pada ekspansi aritmatika , yang tidak dengan sendirinya spesifik untuk Bash (meskipun beberapa cangkang yang sangat tua, non-POSIX-compliant tidak memilikinya,), forloop C-style adalah Bash-isme dan tidak banyak portabel untuk digunakan. kerang lainnya.
Bash tersedia secara luas, terutama pada sistem GNU / Linux seperti Ubuntu, dan (seperti yang telah Anda lihat) juga tersedia di macOS dan banyak sistem lainnya. Mengingat seberapa banyak Anda menggunakan fitur spesifik Bash, Anda mungkin hanya ingin menggunakannya, dan cukup pastikan Anda menggunakan Bash (atau beberapa shell lain yang mendukung fitur yang Anda gunakan) ketika Anda menjalankan skrip Anda.
Namun, Anda dapat menggantinya dengan konstruksi portabel jika Anda mau. Array dan forloop gaya-C mudah diganti; menghasilkan rentang huruf tanpa ekspansi brace (dan tanpa mengkodekannya dalam skrip Anda) adalah bagian yang sedikit rumit.
Pertama, inilah skrip yang mencetak semua huruf latin dengan huruf kecil:
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
- The
seqperintah menghasilkan urutan numerik. $( )melakukan substitusi perintah , jadi $(seq 97 122)diganti dengan output dari seq 97 122. Ini adalah kode karakter untuk amelalui z.
printfPerintah yang kuat dapat mengubah kode karakter menjadi huruf (misalnya, printf '\141'cetakan a, diikuti oleh baris baru ), tetapi kode harus dalam oktal , sementara seqoutput hanya dalam desimal . Jadi saya telah menggunakan printfdua kali: bagian dalam printf %o $imengubah angka desimal (disediakan oleh seq) menjadi oktal, dan diganti menjadi printfperintah luar . (Meskipun juga mungkin untuk menggunakan heksadesimal , itu tidak sederhana dan tampaknya kurang portabel .)
printfinterpret \diikuti oleh angka oktal sebagai karakter dengan kode itu, dan\n sebagai baris baru. Tetapi shell juga digunakan \sebagai karakter pelarian. A \di depan $akan mencegah $dari menyebabkan ekspansi terjadi (dalam hal ini, substitusi perintah ), tapi saya tidak ingin mencegah itu, jadi saya telah lolos dengan yang lain \; itulah alasannya \\. Yang kedua \sebelum ntidak perlu melarikan diri karena, tidak seperti \$, \ntidak memiliki arti khusus pada shell dalam string yang dikutip ganda.
- Untuk informasi lebih lanjut tentang bagaimana tanda kutip ganda dan garis miring terbalik digunakan dalam pemrograman shell, lihat bagian tentang mengutip dalam standar internasional . Lihat juga 3.1.2 Mengutip dalam Manual Referensi Bash , terutama 3.1.2.1 Karakter Escape dan 3.1.2.3 Kutipan Ganda . (Inilah keseluruhan bagian , dalam konteks.) Perhatikan bahwa tanda kutip tunggal (
') juga merupakan bagian penting dari sintaksis mengutip shell, saya hanya tidak menggunakannya dalam skrip itu.
Ini portabel untuk sebagian besar sistem mirip Unix dan tidak bergantung pada shell Bourne-style yang Anda gunakan. Namun, beberapa sistem mirip Unix tidak seqdiinstal secara default (mereka cenderung menggunakan jot, yang tidak diinstal secara default pada kebanyakan sistem GNU / Linux). Anda dapat menggunakan loop dengan expratau substitusi aritmatika untuk meningkatkan portabilitas lebih lanjut, jika Anda perlu:
#!/bin/sh
i=97
while [ $i -le 122 ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Yang menggunakan while-loop dengan para [perintah untuk melanjutkan perulangan hanya ketika $iberada dalam jangkauan.
Alih-alih mencetak seluruh alfabet, skrip Anda mendefinisikan variabel ndan mencetak $nhuruf kecil pertama. Berikut adalah versi skrip Anda yang tidak mengandalkan fitur khusus Bash dan berfungsi di Dash, tetapi mengharuskan seq:
#!/bin/sh
n=3 start=97
for i in $(seq $start $((start + n - 1))); do
printf "\\$(printf %o $i)\n"
done
Menyesuaikan nilai nperubahan berapa banyak huruf yang dicetak, seperti pada skrip Anda.
Ini versi yang tidak memerlukan seq:
#!/bin/sh
n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Di sana, $stopada satu yang lebih tinggi dari kode karakter huruf terakhir yang harus dicetak, jadi saya menggunakan -lt(kurang dari) daripada -le(kurang dari atau sama) dengan [perintah. (Ini juga akan berhasil membuatnyastop=$((i + n - 1)) dan menggunakan [ $i -le $stop ]).