Saya bingung dengan menggunakan tanda kurung tunggal atau ganda. Lihatlah kode ini:
dir="/home/mazimi/VirtualBox VMs"
if [[ -d ${dir} ]]; then
echo "yep"
fi
Ini berfungsi dengan baik meskipun string berisi spasi. Tetapi ketika saya mengubahnya ke braket tunggal:
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then
echo "yep"
fi
Ia mengatakan:
./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected
Ketika saya mengubahnya ke:
dir="/home/mazimi/VirtualBox VMs"
if [ -d "${dir}" ]; then
echo "yep"
fi
Ini bekerja dengan baik. Adakah yang bisa menjelaskan apa yang terjadi? Kapan saya harus memberikan tanda kutip ganda di sekitar variabel "${var}"
untuk mencegah masalah yang disebabkan oleh spasi?
Jawaban:
Braket tunggal
[
sebenarnya adalah alias untuktest
perintah, itu bukan sintaks.Salah satu kelemahan (dari banyak) braket tunggal adalah bahwa jika satu atau lebih operan yang mencoba mengevaluasi mengembalikan string kosong, ia akan mengeluh bahwa ia mengharapkan dua operan (biner). Inilah sebabnya mengapa Anda melihat orang-orang melakukannya
[ x$foo = x$blah ]
,x
jaminan bahwa operan tidak akan pernah mengevaluasi ke string kosong.Braket ganda
[[ ]]
, di sisi lain, adalah sintaks dan jauh lebih mampu daripada[ ]
. Seperti yang Anda ketahui, ia tidak memiliki masalah operan tunggal dan juga memungkinkan sintaksis mirip C dengan>, <, >=, <=, !=, ==, &&, ||
operator.Rekomendasi saya adalah sebagai berikut: Jika penerjemah Anda adalah
#!/bin/bash
, maka selalu gunakan[[ ]]
Penting untuk dicatat bahwa
[[ ]]
tidak didukung oleh semua shell POSIX, namun banyak shell yang mendukungnya sepertizsh
danksh
selainbash
sumber
$foo
ini!
atau(
atau-n
... Masalah itu tidak dimaksudkan untuk menjadi masalah dengan kerang POSIX mana jumlah argumen (samping[
dan]
) tidak lebih besar dari empat.[ x$foo = x$blah ]
sama salahnya dengan[ $foo = $bar ]
.[ "$foo" = "$bar" ]
benar di semua shell yang sesuai dengan POSIX,[ "x$foo" = "x$bar" ]
akan berfungsi di shell seperti Bourne, tetapix
tidak untuk kasus di mana Anda memiliki string kosong tetapi di mana$foo
mungkin!
atau-n
...[
bukan alias untuktest
. Jika ya, makatest
akan menerima tanda kurung siku.test -n foo ]
. Tetapitest
tidak, dan[
membutuhkan satu.[
identik dengantest
dalam semua hal lain, tapi bukan itu caraalias
kerjanya. Bash mendeskripsikan[
dantest
sebagai builtin shell , tetapi[[
sebagai kata kunci shell .>=
dan<=
The
[
perintah perintah biasa. Meskipun sebagian besar shell menyediakannya sebagai built-in untuk efisiensi, shell mematuhi aturan sintaksis normal shell.[
persis sama dengantest
, kecuali yang[
membutuhkan]
argumen terakhir dantest
tidak.Kurung ganda
[[ … ]]
adalah sintaks khusus. Mereka diperkenalkan di ksh (beberapa tahun setelah[
) karena[
dapat merepotkan untuk digunakan dengan benar dan[[
memungkinkan beberapa tambahan bagus baru yang menggunakan karakter khusus shell. Misalnya, Anda bisa menuliskarena seluruh ekspresi kondisional diuraikan oleh shell, sedangkan
[ $x = foo && $y = bar ]
pertama-tama akan dibagi menjadi dua perintah[ $x = foo
dan$y = bar ]
dipisahkan oleh&&
operator. Demikian pula tanda kurung ganda memungkinkan hal-hal seperti sintaksis pencocokan pola, misalnya[[ $x == a* ]]
untuk menguji apakah nilaix
diawali dengana
; dalam kurung tunggal ini akan diperluasa*
ke daftar file yang namanya dimulai dengana
di direktori saat ini. Kurung ganda pertama kali diperkenalkan dalam ksh dan hanya tersedia dalam ksh, bash, dan zsh.Di dalam tanda kurung tunggal, Anda perlu menggunakan tanda kutip ganda di sekitar substitusi variabel, seperti di sebagian besar tempat lain, karena mereka hanya argumen untuk perintah (yang kebetulan adalah
[
perintah). Di dalam tanda kurung ganda, Anda tidak perlu tanda kutip ganda, karena shell tidak melakukan pemisahan kata atau globbing: ia menguraikan ekspresi kondisional, bukan perintah.Pengecualian adalah di
[[ $var1 = "$var2" ]]
mana Anda membutuhkan tanda kutip jika Anda ingin melakukan perbandingan string byte-ke-byte, jika tidak,$var2
akan menjadi pola yang cocok$var1
.Satu hal yang tidak dapat Anda lakukan
[[ … ]]
adalah menggunakan variabel sebagai operator. Misalnya, ini legal (tetapi jarang bermanfaat):Dalam contoh Anda
perintah dalam
if
adalah[
dengan 4 argumen-d
,/home/mazimi/VirtualBox
,VMs
dan]
. Shell mengurai-d /home/mazimi/VirtualBox
dan kemudian tidak tahu apa yang harus dilakukanVMs
. Anda perlu mencegah pemisahan kata${dir}
untuk mendapatkan perintah yang dibuat dengan baik.Secara umum, selalu gunakan tanda kutip ganda di sekitar penggantian variabel dan perintah kecuali jika Anda tahu Anda ingin melakukan pemisahan kata dan globbing pada hasilnya. Tempat-tempat utama di mana aman untuk tidak menggunakan tanda kutip ganda adalah:
foo=$bar
(tetapi perhatikan bahwa Anda membutuhkan tanda kutip ganda dalamexport "foo=$bar"
atau dalam penugasan array sepertiarray=("$a" "$b")
);case
pernyataancase $foo in …
:;=
atau==
operator (kecuali jika Anda melakukan ingin pencocokan pola):[[ $x = "$y" ]]
.Dalam semua ini, itu benar untuk menggunakan tanda kutip ganda, jadi Anda mungkin juga melewatkan aturan lanjutan dan menggunakan tanda kutip sepanjang waktu.
sumber
[
memang dari Sistem III pada tahun 1981 , saya pikir itu lebih tua.Tersirat dalam pertanyaan ini adalah
${variable_name}
tidak berarti apa yang Anda pikirkan ...... jika Anda pikir itu ada hubungannya dengan masalah yang disebabkan oleh spasi (dalam nilai variabel). baik untuk ini:
${variable_name}
dan tidak ada lagi! 1 tidak ada gunanya kecuali Anda segera mengikutinya dengan karakter yang bisa menjadi bagian dari nama variabel: huruf (-atau-), garis bawah (), atau digit (-). Dan bahkan kemudian, Anda dapat mengatasinya:
${variable_name}
A
Z
a
z
_
0
9
Saya tidak mencoba untuk mencegah penggunaannya -
echo "${bar}d"
mungkin merupakan solusi terbaik di sini - tetapi untuk mencegah orang-orang dari bergantung pada kawat gigi daripada tanda kutip, atau menerapkan kawat gigi secara naluriah dan kemudian bertanya, "Sekarang, apakah saya perlu tanda kutip, juga? ” Anda harus selalu menggunakan tanda kutip kecuali Anda memiliki alasan kuat untuk tidak melakukannya, dan Anda yakin tahu apa yang Anda lakukan._________________
1 Kecuali, tentu saja, untuk fakta bahwa bentuk perluasan parameter yang lebih bagus , misalnya, dan , dibangun di atas sintaks. Selain itu, Anda perlu menggunakan , dll., Untuk referensi parameter posisi 10, 11, dll. - kutipan tidak akan membantu Anda.
${parameter:-[word]}
${parameter%[word]}
${parameter}
${10}
${11}
sumber
Untuk menangani spasi dan karakter | kosong khusus dalam variabel, Anda harus selalu melingkupinya dengan tanda kutip ganda. Mengatur IFS yang tepat juga merupakan praktik yang baik.
Dianjurkan: http://www.dwheeler.com/essays/filenames-in-shell.html
sumber