Sejauh yang saya tahu, [[
adalah versi yang disempurnakan [
, tapi saya bingung ketika saya melihat [[
sebagai kata kunci dan [
ditampilkan sebagai builtin.
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP berkata
Sebuah builtin mungkin merupakan sinonim dari perintah sistem dengan nama yang sama, tetapi Bash menambahkannya secara internal. Sebagai contoh, perintah echo Bash tidak sama dengan / bin / echo, meskipun perilaku mereka hampir identik.
dan
Kata kunci adalah kata, token, atau operator yang dicadangkan. Kata kunci memiliki arti khusus untuk shell, dan memang merupakan blok bangunan dari sintaks shell. Sebagai contoh, untuk, sementara, lakukan, dan! adalah kata kunci. Mirip dengan builtin, kata kunci dikodekan ke dalam Bash, tetapi tidak seperti builtin, kata kunci tidak dengan sendirinya merupakan perintah, tetapi subunit dari perintah yang dibangun. [2]
Bukankah itu berarti keduanya [
dan [[
kata kunci? Apakah ada sesuatu yang saya lewatkan di sini? Juga, tautan ini menegaskan kembali bahwa keduanya [
dan [[
harus memiliki jenis yang sama.
sumber
if "[" $x -eq 3 ]
bekerja seperti yang diharapkan (karena Bash mencari perintah yang disebut[
, dan ini ada), tapiif "[[" $x -eq 3 ]]
tidak tidak bekerja (karena sekali lagi Bash mencari perintah dari nama yang tepat, tetapi tidak ada[[
perintah)./usr/bin/echo
, tapi itu tidak berarti itu bukan builtin .Jawaban:
Perbedaan antara
[
dan[[
sangat mendasar.[
adalah sebuah perintah. Argumennya diproses sama seperti argumen perintah lainnya diproses. Sebagai contoh, pertimbangkan:Shell akan memperluas
$name
dan melakukan kedua membelah kata dan generasi nama file pada hasil, hanya seperti itu untuk perintah lain.Sebagai contoh, berikut ini akan gagal:
Agar ini berfungsi dengan benar, kutipan diperlukan:
[[
adalah kata kunci shell dan argumennya diproses sesuai dengan aturan khusus. Sebagai contoh, pertimbangkan:Shell akan memperluas
$name
tetapi, tidak seperti perintah lain, ia akan melakukan tidak membelah kata atau generasi nama file pada hasil. Misalnya, berikut ini akan berhasil meskipun ruang yang disematkan diname
:Ringkasan
[
adalah perintah dan tunduk pada aturan yang sama dengan semua perintah lain yang dijalankan shell.Karena
[[
kata kunci, bukan perintah, shell memperlakukannya secara khusus dan beroperasi di bawah aturan yang sangat berbeda.sumber
man bash
. Lihat, khususnya, bagian yang berjudul "SIMPLE COMMAND EXPANSION" dan "COMMAND EXECUTION". Selain[[
, bash lain kata kunci termasukif
,then
,while
, dan 'kasus'. Tidak ada aturan umum untuk kata kunci: setiap kata kunci adalah kasus khusus.man bash
termasuk perincian untuk masing-masing.Dalam V7 Unix - di mana shell Bourne memulai debutnya -
[
dipanggiltest
, dan itu hanya ada sebagai/bin/test
. Jadi, kode yang Anda tulis hari ini adalah:Anda akan menulis sebagai
Notasi kedua ini masih ada, dan saya merasa lebih jelas tentang apa yang terjadi: Anda memanggil perintah yang memanggil
test
argumen yang mengevaluasi dan mengembalikan kode status keluar yangif
digunakan untuk memutuskan apa yang harus dilakukan selanjutnya. Perintah itu dapat dibangun ke dalam shell, atau mungkin program eksternal.¹[
sebagai alternatif untuktest
datang kemudian .² Ini mungkin merupakan sinonim untuk builtintest
, tetapi juga disediakan seperti/bin/[
pada sistem modern untuk shell yang tidak memilikinya sebagai builtin.[
dantest
dapat diimplementasikan menggunakan kode yang sama. Ini adalah kasus untuk/bin/[
dan/bin/test
pada OS X, di mana ini adalah tautan keras ke executable yang sama. Sebagai akibatnya, implementasi sepenuhnya mengabaikan trailing]
: itu tidak mengharuskannya jika Anda menyebutnya/bin/[
, dan tidak mengeluh jika Anda lakukan memberikan kepada/bin/test
.⁴Tak satu pun dari sejarah itu yang memengaruhi
[[
, karena tidak pernah ada program primordial yang disebut[[
. Itu ada murni di dalam shell yang mengimplementasikannya sebagai ekstensi ke shell POSIX .Bagian dari perbedaan antara "bawaan" dan "kata kunci" adalah karena sejarah ini. Ini juga mencerminkan fakta bahwa aturan sintaks untuk
[[
ekspresi parsing berbeda, seperti yang ditunjukkan dalam jawaban John1024 .⁵Catatan kaki:
Ketika Anda melihatnya seperti itu, itu menjelaskan mengapa Anda harus meletakkan spasi di
[
dalam skrip shell, tidak seperti cara kurung dan kurung bekerja di sebagian besar bahasa pemrograman lainnya. Jika parser perintah shell diizinkanif["$x"...
, itu juga harus mengizinkaniftest"$x"...
Itu terjadi sekitar tahun 1980.
/bin/[
tidak ada dalam salinan Ancient Unix V7 saya dari tahun 1979, juga tidakman test
mendokumentasikannya sebagai alias. Di halaman masuk man yang sesuai saya miliki dalam salinan pra-rilis dari Sistem III pengguna dari 1980, itu adalah terdaftar.ls -i /bin/[ /bin/test
Tapi jangan mengandalkan perilaku ini. The Bash built-in versi
[
tidak memerlukan penutupan]
, dan built-in yangtest
pelaksanaannya akan mengeluh jika Anda tidak memberikan itu.Perbedaan perintah builtin vs eksternal juga penting karena alasan lain: kedua implementasi mungkin berperilaku berbeda. Ini adalah kasus
echo
pada banyak sistem. Karena hanya ada satu implementasi, tidak ada perbedaan yang perlu dibuat untuk kata kunci.sumber
builtin
dankeyword
perbedaan antara[
dan[[
ketika kedua menyediakan fungsi yang sama (kecuali kenyataan bahwa[[
dilengkapi dengan fitur lebih[
)?[[
menjadi kata kunci memungkinkan bash untuk melakukan hal-hal yang tidak mungkin dilakukan[
- misalnya mengutip tidak perlu banyak waktu, karena shell sadar bahwa itu adalah variabel. Itu mengatakan, pemrosesan baris perintah terpengaruh ketika kata kunci digunakan, tetapi tidak ketika builtin digunakan - itu terjadi jauh kemudian.[
builtin, tetapi kode tersebut dikomentari.cd
adalah builtin, tetapi tidak membayangi apa pun (cd
tidak dapat diimplementasikan sebagai program eksternal).[[
kata kunci memungkinkan shell untuk menggunakan aturan penguraian khusus untuk argumennya. Jadi, sayangnya, upvote saya masuk ke John1024.[
awalnya hanya perintah eksternal, nama lain untuk/bin/test
. Tetapi beberapa perintah, seperti[
danecho
, digunakan begitu sering dalam skrip shell sehingga shell implementors memutuskan untuk menyalin kode langsung ke shell itu sendiri, daripada harus menjalankan proses lain setiap kali mereka digunakan. Itu mengubah perintah-perintah ini menjadi "bawaan", meskipun Anda masih dapat menjalankan program eksternal melalui path lengkapnya.[[
datang jauh kemudian. Meskipun builtin diimplementasikan secara internal di dalam shell, itu diurai seperti perintah eksternal. Seperti yang dijelaskan dalam jawaban John1024, ini berarti bahwa variabel yang tidak dikutip akan menyelesaikan pemisahan kata, dan token menyukai>
dan<
diproses sebagai pengalihan I / O. Ini membuat penulisan perbandingan perbandingan yang rumit menjadi tidak nyaman.[[
dibuat sebagai sintaksis shell, sehingga bisa diurai secara ideosinkratis. Dalam[[
variabel tidak mendapatkan pemisahan kata,<
dan>
dapat digunakan sebagai operator pembanding,=
dapat berperilaku berbeda tergantung pada apakah parameter berikutnya dikutip atau tidak, dll. Ini semua adalah kemudahan yang membuat[[
lebih mudah digunakan daripada[
perintah / builtin tradisional .Mereka tidak bisa hanya membaca ulang
[
sebagai sintaksis seperti ini karena itu akan menjadi perubahan yang tidak kompatibel ke jutaan skrip. Dengan menggunakan[[
sintaks baru , yang sebelumnya tidak ada, mereka benar-benar dapat mengubah cara itu digunakan dengan cara yang kompatibel ke atas.Ini mirip dengan evolusi yang menghasilkan
$((...))
sintaks untuk ekspresi aritmatika, yang sebagian besar menggantikanexpr
perintah tradisional .sumber
Yang lebih baru
[[
dibash
adalah optimasi dari[
.Klasik
[
memiliki satu kelemahan besar, ketika itu sering digunakan untuk melakukan operasi sepele: itu akan menelurkan proses baru setiap kali:(Ini menciptakan ruang alamat baru hanya untuk membandingkan
0
dan1
! Setiap kali!)Saya pikir poin utama dari penambahan
[[
adalah membuat evaluasi ekspresi di dalam[
tidak menelurkan proses tambahan. Tetapi bagaimana cara[
kerjanya tidak bisa diubah - itu akan menciptakan banyak kebingungan dan masalah. Jadi, optimasi diimplementasikan dengan nama baru, dengan cara yang lebih efisien, yaitu perintah builtin shell.Itu menjadi kata kunci dalam sintaksis shell sebagai efek samping.
Pada saat
[
pertama kali digunakan, itu adalah cara yang tepat untuk melakukannya dengan proses eksternal.sumber
[
awalnya merupakan perintah eksternal, itu ditambahkan sebagai built-in ke shell cukup awal, mungkin pada saat Unix System III dirilis dan pasti sebelum Unix System V dirilis. Jadi, 'proses ekstra' belum menjadi masalah sejak lama. Namun, sintaks tetap tidak berubah - itu diperlakukan seolah-olah itu akan menjadi perintah eksternal.[
keduanya - itu berarti beberapa perubahan ...