Saya hanya ingin tahu apa sebenarnya perbedaan antara keduanya
[[ $STRING != foo ]]
dan
[ $STRING != foo ]
adalah, selain dari yang terakhir ini adalah posix-compliant, ditemukan di sh dan yang pertama adalah ekstensi yang ditemukan di bash.
Saya hanya ingin tahu apa sebenarnya perbedaan antara keduanya
[[ $STRING != foo ]]
dan
[ $STRING != foo ]
adalah, selain dari yang terakhir ini adalah posix-compliant, ditemukan di sh dan yang pertama adalah ekstensi yang ditemukan di bash.
Jawaban:
Ada beberapa perbedaan. Menurut pendapat saya, beberapa yang paling penting adalah:
[
adalah builtin di Bash dan banyak kerang modern lainnya. Builtin [
mirip dengan test
dengan persyaratan tambahan penutupan ]
. Buildin [
dan test
meniru fungsi /bin/[
dan /bin/test
bersama dengan keterbatasan mereka sehingga skrip akan kompatibel. Executable asli masih ada sebagian besar untuk kepatuhan POSIX dan kompatibilitas mundur. Menjalankan perintah type [
di Bash menunjukkan bahwa [
diartikan sebagai builtin secara default. (Catatan: which [
hanya mencari executable di PATH dan setara dengan type -p [
)[[
tidak kompatibel, itu tidak akan selalu berfungsi dengan /bin/sh
poin apa pun . Jadi [[
adalah pilihan Bash / Zsh / Ksh yang lebih modern.[[
dibangun ke dalam shell dan tidak memiliki persyaratan warisan, Anda tidak perlu khawatir tentang pemisahan kata berdasarkan variabel IFS untuk mengacaukan variabel yang mengevaluasi string dengan spasi. Oleh karena itu, Anda tidak benar-benar perlu memasukkan variabel dalam tanda kutip ganda.Sebagian besar, sisanya hanya beberapa sintaks yang lebih bagus. Untuk melihat lebih banyak perbedaan, saya merekomendasikan tautan ini ke jawaban FAQ: Apa perbedaan antara tes, [dan [[? . Bahkan, jika Anda serius tentang skrip bash, saya sarankan membaca seluruh wiki , termasuk FAQ, Perangkap , dan Panduan. Bagian uji dari bagian panduan menjelaskan perbedaan-perbedaan ini juga, dan mengapa menurut penulis [[
pilihan yang lebih baik jika Anda tidak perlu khawatir menjadi portabel. Alasan utamanya adalah:
< >
dengan garis miring terbalik agar mereka tidak dievaluasi sebagai pengalihan input, yang benar-benar dapat mengacaukan beberapa hal dengan menimpa file. Ini lagi kembali [[
menjadi builtin. Jika [(tes) adalah program eksternal shell harus membuat pengecualian dalam cara mengevaluasi <
dan >
hanya jika /bin/test
dipanggil, yang tidak akan masuk akal.Pendeknya:
[adalah Builtin bash
[[]] adalah Kata Kunci bash
Kata kunci: Kata kunci sangat mirip builtin, tetapi perbedaan utama adalah bahwa aturan penguraian khusus berlaku untuk mereka. Misalnya, [adalah built-in bash, sementara [[adalah kata kunci bash. Keduanya digunakan untuk menguji hal-hal, tetapi karena [[adalah kata kunci dan bukan builtin, itu mendapat manfaat dari beberapa aturan penguraian khusus yang membuatnya jauh lebih mudah:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
Contoh pertama mengembalikan kesalahan karena bash mencoba mengalihkan file b ke perintah [a]. Contoh kedua sebenarnya melakukan apa yang Anda harapkan. Karakter <tidak lagi memiliki arti khusus dari operator Pengalihan File.
Sumber: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[
adalah perintah shell POSIX; tidak perlu dibangun. ]
Hanya argumen yang dicari oleh perintah itu, sehingga sintaksnya seimbang. Perintah ini adalah sinonim untuk test
kecuali yang test
tidak mencari penutupan ]
.
Perbedaan perilaku
Beberapa perbedaan pada 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, <
pengalihan, &&
dan ||
menggabungkan beberapa perintah, ( )
menghasilkan subkulit kecuali lolos \
, dan perluasan kata terjadi seperti biasa.
[[ X ]]
adalah konstruksi tunggal yang membuat X
diurai secara ajaib. <
, &&
, ||
Dan ()
diperlakukan khusus, dan aturan kata membelah berbeda.
Ada juga perbedaan lebih lanjut seperti =
dan =~
.
Dalam Bashese: [
adalah perintah bawaan , dan [[
merupakan kata kunci: https://askubuntu.com/questions/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: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
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 by[ a = a ] && [ b = b ]
: POSIX dan setara yang dapat diandalkan(
[[ (a = a || a = b) && a = b ]]
: Salah[ ( a = a ) ]
: kesalahan sintaksis, ()
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? ]]
: true, POSIX memperpanjang kecocokan ekspresi reguler , ?
tidak glob berkembang[ a =~ a ]
: kesalahan sintaks. Tidak 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
atau b
(suka +
atau index
) dan melakukan perbandingan numerik jika a
dan b
terlihat seperti bilangan bulat desimal. expr "x$a" '<' "x$b"
bekerja di sekitar keduanya.
³ dan juga gagal untuk beberapa nilai a
atau b
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.
printf 'ab' | grep -Eq 'ab?'
dalam if [ … ]
?
if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
. []
adalah perintah sama seperti grep
. The ()
mungkin tidak diperlukan pada perintah yang saya tidak yakin: Saya menambahkan itu karena |
, tergantung pada bagaimana Bash mem-parsing hal. Jika tidak ada |
saya yakin Anda bisa menulis saja if cmd arg arg; then
.
()
sepertinya tidak perlu : stackoverflow.com/questions/8965509/…
Single Bracket yaitu []
POSIX shell compliant untuk melampirkan ekspresi kondisional.
Kurung Ganda yaitu [[]]
versi yang ditingkatkan (atau ekstensi) dari versi POSIX standar, ini didukung oleh bash dan cangkang lainnya (zsh, ksh).
Di bash, untuk perbandingan numerik yang kami gunakan eq
, ne
, lt
dan gt
, dengan kurung ganda untuk perbandingan bisa kita gunakan ==
, !=
, <,
dan >
secara harfiah.
[
adalah sinonim untuk perintah tes. Bahkan jika itu dibangun ke shell itu menciptakan proses baru.[[
adalah versi baru yang disempurnakan, yang merupakan kata kunci, bukan program. sebagai contoh:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
if
pernyataan, lihat mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D