Saya membaca contoh bash tentang if
tetapi beberapa contoh ditulis dengan tanda kurung tunggal:
if [ -f $param ]
then
#...
fi
lainnya dengan tanda kurung ganda:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
Apa bedanya?
bash
if-statement
rkmax
sumber
sumber
Jawaban:
Tunggal
[]
adalah tes kondisi yang sesuai dengan posix shell.Double
[[]]
adalah ekstensi ke standar[]
dan didukung oleh bash dan shell lainnya (misalnya zsh, ksh). Mereka mendukung operasi tambahan (serta operasi posix standar). Misalnya:||
alih-alih-o
dan mencocokkan regex dengan=~
. Daftar perbedaan yang lebih lengkap dapat ditemukan di bagian manual bash pada konstruksi kondisional .Gunakan
[]
kapan pun Anda ingin skrip Anda portabel di seluruh shell. Gunakan[[]]
jika Anda ingin ekspresi kondisional tidak didukung oleh[]
dan tidak perlu portabel.sumber
[[ ]]
(misalnya bash with#!/bin/bash
atau#!/usr/bin/env bash
), Anda harus menggunakan opsi portabel. Skrip yang berasumsi / bin / sh mendukung ekstensi seperti ini akan merusak OS seperti rilis Debian dan Ubuntu baru-baru ini di mana bukan itu masalahnya.Perbedaan perilaku
Diuji dalam Bash 4.3.11:
Ekstensi POSIX vs Bash:
[
adalah POSIX[[
adalah ekstensi Bash¹ didokumentasikan di: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsperintah reguler vs sihir
[
hanyalah perintah biasa dengan nama yang aneh.]
hanyalah argumen[
yang mencegah argumen lebih lanjut digunakan.Ubuntu 16.04 sebenarnya memiliki executable yang
/usr/bin/[
disediakan oleh coreutils, tetapi versi built-in bash lebih diutamakan.Tidak ada yang diubah dalam cara Bash mem-parsing perintah.
Secara khusus,
<
adalah pengalihan,&&
dan||
menggabungkan beberapa perintah,( )
menghasilkan subkulit kecuali lolos\
, dan perluasan kata terjadi seperti biasa.[[ X ]]
adalah konstruksi tunggal yang membuatX
diurai secara ajaib.<
,&&
,||
Dan()
diperlakukan khusus, dan aturan kata membelah berbeda.Ada juga perbedaan lebih lanjut seperti
=
dan=~
.Di Bashese:
[
adalah perintah bawaan , dan[[
merupakan kata kunci: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword<
[[ a < b ]]
: perbandingan leksikografis[ a \< b ]
: Sama seperti di atas.\
diperlukan atau jika tidak pengalihan seperti untuk perintah lain. Ekstensi bash.expr a \< b > /dev/null
: POSIX equivalent², lihat: Bagaimana menguji string untuk lexicographic kurang dari atau sama di Bash?&&
dan||
[[ a = a && b = b ]]
: benar, logis dan[ a = a && b = b ]
: kesalahan sintaks,&&
diurai sebagai pemisah perintah ANDcmd1 && cmd2
[ a = a -a b = b ]
: setara, tetapi ditinggalkan oleh POSIX³[ a = a ] && [ b = b ]
: POSIX dan setara yang dapat diandalkan(
[[ (a = a || a = b) && a = b ]]
: Salah[ ( a = a ) ]
: kesalahan sintaks,()
ditafsirkan sebagai subkulit[ \( a = a -o a = b \) -a a = b ]
: ekuivalen, tetapi()
ditinggalkan oleh POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
Setara dengan POSIX 5pemisahan kata dan pembuatan nama file berdasarkan ekspansi (split + glob)
x='a b'; [[ $x = 'a b' ]]
: true, kutipan tidak diperlukanx='a b'; [ $x = 'a b' ]
: kesalahan sintaks, diperluas ke[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: kesalahan sintaks jika ada lebih dari satu file di direktori saat ini.x='a b'; [ "$x" = 'a b' ]
: Setara POSIX=
[[ ab = a? ]]
: benar, karena tidak cocok dengan pola (* ? [
adalah sihir). Tidak glob berkembang ke file dalam direktori saat ini.[ ab = a? ]
:a?
glob berkembang. Jadi mungkin benar atau salah tergantung pada file di direktori saat ini.[ ab = a\? ]
: false, bukan ekspansi glob=
dan==
sama di keduanya[
dan[[
, tetapi==
merupakan ekstensi Bash.case ab in (a?) echo match; esac
: Setara POSIX[[ ab =~ 'ab?' ]]
: false 4 , kehilangan sihir dengan''
[[ ab? =~ 'ab?' ]]
: benar=~
[[ ab =~ ab? ]]
: benar, POSIX memperpanjang kecocokan ekspresi reguler ,?
tidak glob berkembang[ a =~ a ]
: kesalahan sintaks. Tidak ada yang setara dengan bash.printf 'ab\n' | grep -Eq 'ab?'
: Setara POSIX (hanya data garis tunggal)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: Setara POSIX.Rekomendasi : selalu gunakan
[]
.Ada setara POSIX untuk setiap
[[ ]]
konstruk yang pernah saya lihat.Jika Anda menggunakan
[[ ]]
Anda:[
hanyalah perintah biasa dengan nama yang aneh, tidak ada semantik khusus yang terlibat.¹ Terinspirasi dari
[[...]]
konstruksi yang setara di shell Korn² tetapi gagal untuk beberapa nilai
a
ataub
(suka+
atauindex
) dan melakukan perbandingan numerik jikaa
danb
terlihat seperti bilangan bulat desimal.expr "x$a" '<' "x$b"
bekerja di sekitar keduanya.³ dan juga gagal untuk beberapa nilai
a
ataub
suka!
atau(
.4 di bash 3.2 dan di atas dan kompatibilitas yang disediakan untuk bash 3.1 tidak diaktifkan (seperti dengan
BASH_COMPAT=3.1
)5 meskipun pengelompokan (di sini dengan
{...;}
kelompok perintah alih-alih(...)
yang akan menjalankan subkulit yang tidak perlu) tidak diperlukan karena operator||
dan&&
shell (sebagai lawan dari||
dan&&
[[...]]
operator atau-o
/-a
[
operator) memiliki prioritas yang sama. Jadi[ a = a ] || [ a = b ] && [ a = b ]
akan setara.sumber
[]
harus dibaca sebagai preferensi saya : gunakan[]
jika Anda tidak ingin kehilangan portabilitas . Seperti yang dinyatakan di sini : Jika portabilitas / kesesuaian dengan POSIX atau BourneShell menjadi perhatian, sintaks lama harus digunakan. Jika di sisi lain skrip membutuhkan BASH, Zsh, atau KornShell, sintaks baru biasanya lebih fleksibel, tetapi tidak selalu kompatibel ke belakang. Saya lebih suka pergi[[ ab =~ ab? ]]
jika saya bisa dan tidak memiliki kekhawatiran tentang kompatibilitas mundur daripadaprintf 'ab' | grep -Eq 'ab?'
Di dalam kurung tunggal untuk pengujian kondisi (yaitu [...]), beberapa operator seperti tunggal
=
didukung oleh semua shell, sedangkan penggunaan operator==
tidak didukung oleh beberapa shell yang lebih lama.Di dalam tanda kurung ganda untuk pengujian kondisi (yaitu [[...]]), tidak ada perbedaan antara menggunakan
=
atau==
di shell yang lama atau yang baru.Sunting: Saya juga harus mencatat bahwa: Dalam bash, selalu gunakan tanda kurung ganda [[...]] jika memungkinkan, karena lebih aman daripada tanda kurung tunggal. Saya akan menggambarkan mengapa dengan contoh berikut:
jika $ var adalah null / kosong, maka inilah yang dilihat skrip:
yang akan merusak skrip Anda. Solusinya adalah dengan menggunakan kurung ganda, atau selalu ingat untuk menempatkan tanda kutip di sekitar variabel Anda (
"$var"
). Kurung ganda adalah praktik pengkodean defensif yang lebih baik.sumber
[[
adalah kata kunci bash mirip dengan (tetapi lebih kuat dari)[
perintah.Lihat
http://mywiki.wooledge.org/BashFAQ/031 dan http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
Kecuali Anda menulis untuk POSIX sh, sebaiknya
[[
.sumber
Anda dapat menggunakan tanda kurung ganda untuk pencocokan regex ringan, misalnya:
if [[ $1 =~ "foo.*bar" ]] ; then
(selama versi bash yang Anda gunakan mendukung sintaks ini)
sumber
Bash manual mengatakan:
(Perintah tes identik dengan [])
sumber