Misalnya, perintah berikut ini tidak berfungsi:
if [[-e xyz]]; then echo File exists;fi
ksh memberikan kesalahan berikut
[[-e: command not found
Apakah itu karena "[[-" ambigu?
command-line
syntax
ksh
AcBap
sumber
sumber
[[
adalah kata kunci - mungkin pohon parsing shell mengharuskan kata kunci harus ditentukan oleh spasiJawaban:
Penjelasan yang paling sederhana adalah, karena dalam manual itu muncul
[[ expression ]]
sehingga harus ada ruang antara[[
danexpression
dan penutup]]
. Tetapi tentu saja kita dapat mencoba untuk melihatnya secara lebih mendalam. Kerang memiliki tata bahasa yang agak rumit dan sangat bergantung pada konsep "pemisahan kata". Secara khusus, ksh (1) menyatakan manual:Jadi seperti yang dinyatakan dalam manual, urutan karakter
[[-e
dianggap kata shell.ksh
akan mencari perintah seperti itu dalam daftar built-in dan operator khusus (sukafor
atauwhile
), kemudian mencari perintah eksternal - dan voilà - tidak ada yang ditemukan, maka ada pesan kesalahan tentang perintah tidak ditemukan.Dalam hal ini
[[
juga bukan meta-karakter khusus. Jika ya,-e
bagian dalam[[-e
akan dianggap sebagai kata shell, bukan argumen untuk[[
dirinya sendiri. Namun,[[
dijelaskan sebagai perintah majemuk, dan manual mengatakan sebagai berikut:Jadi agar
[[
dapat dikenali sebagai perintah majemuk, itu harus menjadi kata pertama dari perintah atau daftar perintah, yang menurut definisi sebelumnya dari "kata" menyiratkan itu harus dipisahkan oleh spasi, tab, atau baris baru dari lainnya kata-kata / argumen.Anda telah bertanya di komentar : "Mengapa parser tidak bisa berhenti begitu menemukan" [["pola, dan memperlakukan itu sebagai awal dari perintah bersyarat?" Jawaban singkat mungkin karena 1) pengaruh
[
sintaksis karena awalnya merupakan perintah eksternal, dan untuk kepatuhan standar POSIX ada sebagai perintah eksternal bahkan hari ini, dan 2) karena parser shell dibangun demikian. Shell parser dapat mengenali karakter khusus yang tidak dibatasi ruang:echo $((2+2))
dan(echo foobar)
berfungsi dengan baik. Mungkin di masa depan ketikaksh
pengembangan dilanjutkan atau tampaknya ada percabangan atau klon (sepertimksh
ataupdksh
) seseorang akan mengimplementasikan sintaksis tanpa spasi di[[-e
.Lihat juga:
[[
disebut "kata yang dilindungi undang-undang" (lihat bagian 2.9 dari Bahasa Perintah Shell ). Menurut definisi POSIX, kata yang dipesan harus dibatasi oleh spasi. Sebaliknya(
adalah operator, dan negara standar di bagian 2.9 "representasi termasuk spasi antara token di beberapa tempat di mana<blank>
s tidak diperlukan (ketika salah satu token adalah operator)". Lihat diskusi terkait: POSIX Shell Grammar: Mengapa Brace Group Membutuhkan Ruang Pertama Tapi Subshell Tidak?sumber
char
adalah kata kunci tetapi Anda masih tidak dapat menulischarsomeletter = 'A';
dan berharap parser berhenti setelah melihatchar
.i--<=++j
, dan kompiler tidak memiliki masalah menguraikan itu sebagaii -- <= ++ j
._
). Ksh memiliki(
sebagai operator , dan(echo hello)
mem - parsing sebagai( echo hello )
. Ini telahif
,{
,[[
, dan lainnya kata kunci , danifx
,{x
, dan[[x
masing-masing satu token - seperti bagaimanacharsomeletter
adalah salah satu C tanda. Sebaliknya, tanda kutip(x
dalam ksh adalah dua token - seperti bagaimanai--
dua token dalam C. Apa yang secara konseptual berarti menjadi operator berbeda antara shell gaya Bourne (seperti ksh) dan C. Tapi Peter A. Schneider menunjukkan sebuah kesamaan leksikal nyata .Yang penting untuk dicatat adalah itu
[
adalah perintah, dan kata kunci shell[[
dalam bash dan ksh didasarkan pada[
.[[
digunakan dalam cara yang mirip dengan[
. Kadang-kadang Anda bahkan dapat mengganti[
]
dengan[[
]]
tanpa perubahan perilaku. Dengan[
, seperti perintah apa pun, spasi wajib antara perintah dan argumennya. Hal yang sama berlaku untuk[[
.Kami dulu hanya punya
/usr/bin/[
. Sekarang sebagian besar shell sudah[
dibangun untuk efisiensi — tetapi sintaksnya sama. Dalam shell yang menyediakan[[
, itu berfungsi sebagai alternatif yang lebih fleksibel[
.Berikut ini deskripsi untuk
[
di bash:Jadi
[
sama dengantest
(selain mengharapkan]
argumen di akhir).help test
akan memberikan detail lebih banyak tentang itu. Anda dapat membandingkan ini denganhelp [[
.Ada juga halaman manual untuk perintah eksternal
[
(man \[
).Dalam kasus
[
juga[[
adalah perintah, ada. Kata lengkapnya[[-e
adalah.if [[-e
membuatnya menjadi ujian untuk benar / salah. Jadi, apakah[[-e
ada perintah ?Iya. Atau tidak.
[[-e
adalah apa adanya: tidak ada yang dipahami shell sehingga ia menganggap itu adalah perintahnya sendiri. ;-)sumber
[[-e
adalah nama perintah yang berpotensi valid (jika terlihat aneh).Ruang adalah pembatas dan diperlukan. Seperti yang Anda lihat dari
shellcheck
:(Baik ksh dan bash mendukung
[[
dan tidak bekerja tanpa spasi. Shellcheck memberikan output yang persis sama dengan skrip ksh dan bash yang berisi baris buggy.)Mengapa pembatas diperlukan karena token dan leksikon .
sumber
ksh
shell dalam pertanyaan. Bash meminjam[[
operator dariksh
dan dalam pertanyaan ini perilaku mereka identik, tapi saya akan berhati-hati dari asumsi karena ada beberapa perbedaan yang signifikan antaraksh
danbash
perilaku dan internal. Itu hanya karena shellcheck berfungsi pada skrip bash, mungkin itu bukan alat yang tepat untuk skrip ksh. Hanya sesuatu yang perlu diingat ketika mendekati kerang yang berbeda[[
aturan bawaan . Saya sama sekali tidak dapat menyimpulkan bahwaksh
itu adalah shell yangshellcheck
dapat menemukan kesalahan. Saya berharap orang lain menghargaiksh
danbash
dua penafsir yang berbeda. Terima kasih telah menyebutkannya. Juga patut dicatat[[
adalah bash yang dibangun sementara[
adalah perintah eksternal.[
juga built-in di bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Tapi Anda tidak jauh -[
atautest
diharuskan menjadi perintah eksternal. Pada masa shell Bourne asli[
sebenarnya merupakan perintah eksternal, dan masih ada saat ini/usr/bin/[
karena POSIX mengharuskannya menjadi perintah eksternal pubs.opengroup.org/onlinepubs/009695399/utilities/test.html Sangat sedikit yang diperlukan oleh POSIX untuk menjadi built-in pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Builtin[
untuk efisiensiksh
; menggunakan hashbang atau-s ksh
. Btw, ksh dan bash memiliki[[
"built in," tapi itu kata kunci , tidak seperti[
, yang merupakan builtin shell . (ksh :;whence -v [ [[
bashtype [ [[
:) Builtin dan perintah eksternal secara sintaksis sama. Salah satu cara[[
berbeda dari itu[
adalah yang[[
menekan beberapa ekspansi dalam argumennya, yang tidak bisa sebagai builtin - sama seperti{
tidak dapat melakukan pengelompokan jika itu builtin. Ini mungkin mengapa{x
(atau[[x
) menjadi satu token terasa aneh. Saya pikir itu benar untuk mengatakan builtin dan kata kunci secara leksikal tetapi tidak mirip secara sintaksis . @SergiyKolodyazhnyy[[
bisa menjadi perintah eksternal! Artinya, ini mungkin program dan bukan sintaks yang didukung oleh shell Anda secara langsung. Mendukung sintaksis tanpa spasi mungkin untukksh
tetapi akan gagal pada sistem dengan eksternal[[
sehingga untuk alasan kompatibilitas lebih baik untuk menjaga ruang yang diperlukan.BusyBox menyediakan
[[
sebagai perintah eksternal , misalnya.sumber
Karena
[[-e
dapat berpartisipasi dalam ekspansi shell (dapat digunakan sepertiuntuk membuat daftar semua file yang dimulai dengan huruf di antara
[
dan secarae
inklusif), itu akan menjadi kekacauan total jika[
dan]
merupakan karakter khusus yang tidak berpartisipasi dalam pemisahan kata yang diatur oleh spasi.sumber