Jawaban:
Perbedaan antara [[ … ]]
dan [ … ]
sebagian besar tercakup dalam menggunakan braket tunggal atau ganda - bash . Yang terpenting, [[ … ]]
adalah sintaks khusus, sedangkan [
nama yang tampak lucu untuk sebuah perintah. [[ … ]]
memiliki aturan sintaksis khusus untuk apa yang ada di dalamnya, [ … ]
tidak.
Dengan kerut tambahan wildcard, berikut cara [[ $a == z* ]]
dievaluasi:
[[ … ]]
konstruksi kondisional di sekitar ekspresi kondisional $a == z*
.==
operator biner, dengan operan $a
dan z*
.a
.==
operator: menguji apakah nilai variabel a
cocok dengan pola z*
.Inilah cara [ $a == z* ]
dievaluasi:
[
perintah dengan argumen yang dibentuk dengan mengevaluasi kata-kata $a
, ==
, z*
, ]
.$a
nilai variabel a
.a
adalah string 6 karakter foo b*
(yang diperoleh misalnya a='foo b*'
) dan daftar file dalam direktori saat ini ( bar
, baz
, qux
, zim
, zum
), maka hasil dari ekspansi adalah daftar kata berikut: [
, foo
, bar
, baz
, ==
, zim
, zum
, ]
.[
dengan parameter yang diperoleh pada langkah sebelumnya.
[
perintah mengeluhkan kesalahan sintaks dan mengembalikan status 2.Catatan: Di [[ $a == z* ]]
, pada langkah 3, nilai a
tidak mengalami pemisahan kata dan pembuatan nama file, karena itu dalam konteks di mana satu kata diharapkan (argumen sebelah kiri dari operator kondisional ==
). Dalam kebanyakan kasus, jika satu kata masuk akal pada posisi itu maka ekspansi variabel berperilaku seperti itu dalam tanda kutip ganda. Namun, ada pengecualian untuk aturan itu: di [[ abc == $a ]]
, jika nilai a
berisi wildcard, maka a
dicocokkan dengan pola wildcard. Sebagai contoh, jika nilai a
is a*
maka [[ abc == $a ]]
benar (karena wildcard *
berasal dari perluasan $a
pertandingan yang tidak dikutip *
) sedangkan [[ abc == "$a" ]]
false (karena karakter biasa*
berasal dari ekspansi yang dikutip $a
tidak cocok bc
). Di dalam [[ … ]]
, tanda kutip ganda tidak membuat perbedaan, kecuali di sisi kanan operator pencocokan string ( =
, ==
, !=
dan =~
).
[
adalah alias untuk test
perintah. Unix Versi 6 memiliki if
perintah, tetapi Versi 7 (1979) datang dengan shell Bourne baru yang memiliki beberapa konstruksi pemrograman termasuk if-then-else-elif-fi, dan Unix versi 7 menambahkan test
perintah yang melakukan sebagian besar "tes" yang dilakukan oleh if
perintah di versi yang lebih lama.
[
dibuat alias untuk test
dan keduanya dibuat dibangun ke shell di Unix System III (1981) . Meskipun perlu dicatat bahwa beberapa varian Unix tidak memiliki [
perintah sampai kemudian setelah itu ( hingga awal 2000-an pada beberapa BSD di mana sh
didasarkan pada cangkang Almquist (sebuah test
builtin selalu dimasukkan dalam ash
sumber, tetapi pada mereka BSD awalnya dinonaktifkan)).
Perhatikan bahwa test
alias [
adalah perintah untuk melakukan "tes", tidak ada penugasan yang dilakukan oleh perintah itu, jadi tidak ada alasan untuk menyatukan antara penugasan dan operator kesetaraan, jadi operator kesetaraan itu =
. ==
hanya didukung oleh beberapa implementasi terbaru dari [
(dan hanya alias untuk =
).
Karena [
tidak lebih dari sebuah perintah, itu diurai dengan cara yang sama seperti perintah lain oleh shell.
Khususnya, dalam contoh Anda $a
, karena tidak dikutip, akan dipecah menjadi beberapa kata sesuai dengan aturan pemisahan kata yang biasa, dan setiap kata akan mengalami generasi nama file alias globbing untuk menghasilkan lebih banyak kata, masing-masing kata tersebut menghasilkan argumen terpisah untuk [
perintah.
Demikian pula, z*
akan diperluas ke daftar nama file di direktori saat ini dimulai dengan z
.
Jadi misalnya, jika $a
ini b* = x
, dan ada z1
, z2
, b1
dan b2
file dalam direktori saat ini, The [
perintah akan mendapatkan 9 argumen: [
, b1
, b2
, =
, x
, ==
, z1
, z2
dan ]
.
[
mem-parsing argumennya sebagai ekspresi kondisional. 9 argumen itu tidak menambahkan hingga ekspresi kondisional yang valid, jadi itu mungkin akan mengembalikan kesalahan.
The [[ ... ]]
konstruk diperkenalkan oleh Korn shell mungkin sekitar tahun 1988 sebagai ksh86a
tahun 1987 tidak memilikinya sementara ksh88
memiliki itu dari awal.
Selain ksh (semua implementasi), [[...]]
juga didukung oleh bash (karena versi 2.02) dan zsh, tetapi ketiga implementasi berbeda dan ada perbedaan antara setiap versi dari shell yang sama meskipun perubahan umumnya kompatibel ke belakang (pengecualian yang terkenal adalah bash's =~
operator yang telah dikenal untuk memecahkan beberapa skrip setelah versi tertentu ketika perilakunya berubah). [[...]]
tidak ditentukan oleh POSIX, atau Unix atau Linux (LSB). Ini telah dipertimbangkan untuk dimasukkan beberapa kali, tetapi tidak dimasukkan sebagai fungsi umum dari itu didukung oleh shell utama sudah dicakup oleh [
perintah dan case-in-esac
konstruk.
Seluruh [[ ... ]]
konstruk membentuk sebuah perintah. Artinya, ia memiliki status keluar (yang merupakan aset paling penting karena merupakan hasil dari evaluasi ekspresi bersyarat), Anda dapat mengirimnya ke perintah lain (meskipun itu tidak akan berguna), dan umumnya menggunakannya di mana pun Anda mau gunakan perintah lain (hanya di dalam shell, karena ini adalah shell konstruksi) tetapi tidak diurai seperti perintah sederhana yang normal. Apa yang ada di dalamnya diuraikan oleh shell sebagai ekspresi kondisional dan aturan umum pemisahan kata dan pembuatan nama file berlaku berbeda.
[[ ... ]]
tidak tahu tentang ==
dari awal dan setara dengan =
1 . Kesalahan ksh (dan menyebabkan kebingungan dan banyak bug) adalah bahwa =
dan ==
bukan operator kesetaraan tetapi operator pencocokan pola (meskipun aspek pencocokan dapat dinonaktifkan dengan mengutip tetapi dengan aturan tidak jelas yang berbeda dari shell ke shell).
Dalam kode Anda di atas [[ $a == z* ]]
, shell akan menguraikannya menjadi beberapa token dalam aturan yang mirip dengan yang biasa, mengenalinya sebagai perbandingan pola yang cocok, memperlakukan z*
sebagai pola untuk mencocokkan dengan konten a
variabel.
Secara umum, lebih sulit menembak diri sendiri dengan kaki [[ ... ]]
daripada menggunakan [
perintah. Tetapi beberapa aturan suka
-a
atau -o
(gunakan beberapa [
perintah dan operator &&
dan ||
shell )Dapat [
diandalkan dengan cangkang POSIX.
[[...]]
dalam shell yang berbeda mendukung operator tambahan seperti -nt
, operator pencocokan regexp ... tetapi daftar dan perilaku bervariasi dari shell ke shell dan versi ke versi.
Jadi, kecuali Anda tahu apa shell dan versi minimum dari itu skrip Anda akan pernah ditafsirkan, mungkin lebih aman untuk tetap dengan [
perintah standar .
1 Pengecualian: [[...]]
telah ditambahkan ke versi bash 2.02
. Sampai 2.03
dimana itu diubah, [[ x = '?' ]]
akan mengembalikan true sementara [[ x == '?' ]]
akan mengembalikan false. Mengutip tidak mencegah pencocokan pola saat menggunakan =
operator di versi tersebut, tetapi melakukannya saat menggunakan ==
.
[ '!' = foo -o a = a ]
di bash
misalnya.
keduanya digunakan untuk mengevaluasi ekspresi dan [[tidak akan bekerja dengan shell bourn POSIX yang lebih lama dan [[juga mendukung pencocokan pola dan regex. contoh coba ini
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]
hanya mendukung regexps di beberapa versi beberapa shell, seperti halnya beberapa versi [
yang mendukung pencocokan regexp. Untuk perbandingan aritemik, dalam cangkang yang mendukung [[
, Anda lebih suka menulis(( n == 0 && y == 0))