pengembangan-web-mp-pd.com

Apa perbedaan antara tanda kurung ganda dan tunggal dalam 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.

451
0x89

Ada beberapa perbedaan. Menurut pendapat saya, beberapa yang paling penting adalah:

  1. [ adalah bawaan di Bash dan banyak shell modern lainnya. Builtin [ mirip dengan test dengan persyaratan tambahan penutupan ]. Builtin [ dan test meniru fungsi /bin/[ dan /bin/test beserta batasannya sehingga skrip akan kompatibel. Executable asli masih ada sebagian besar untuk kepatuhan POSIX dan kompatibilitas mundur. Menjalankan perintah type [ dalam Bash menunjukkan bahwa [ ditafsirkan sebagai builtin secara default. (Catatan: which [ hanya mencari executable di jalur [~ # ~] [~ # ~] dan setara dengan type -p [)
  2. [[ tidak kompatibel, itu tidak akan bekerja dengan apa pun /bin/sh menunjuk ke. Jadi [[ adalah pilihan Bash/Zsh/Ksh) yang lebih modern.
  3. Karena [[ dibangun ke dalam Shell dan tidak memiliki persyaratan warisan, Anda tidak perlu khawatir tentang pemisahan kata berdasarkan [~ # ~] ifs [~ # ~] variabel untuk dikacaukan pada variabel yang mengevaluasi string dengan spasi. Oleh karena itu, Anda tidak perlu memasukkan variabel dalam tanda kutip ganda.

Sebagian besar, sisanya hanya beberapa sintaksis yang lebih bagus. Untuk melihat lebih banyak perbedaan, saya sarankan tautan ini ke FAQ jawaban: Apa perbedaan antara tes, [dan [[? . Sebenarnya, jika Anda serius tentang skrip bash, saya sarankan membaca keseluruhan wiki , termasuk FAQ, Jebakan , dan Panduan. Bagian uji dari bagian panduan menjelaskan ini perbedaan juga, dan mengapa penulis berpikir [[ adalah pilihan yang lebih baik jika Anda tidak perlu khawatir menjadi portabel. Alasan utamanya adalah:

  1. Anda tidak perlu khawatir tentang mengutip sisi kiri tes sehingga benar-benar dibaca sebagai variabel.
  2. Anda tidak perlu melarikan diri kurang dari dan lebih besar dari < > dengan garis miring terbalik agar mereka tidak dievaluasi sebagai pengalihan input, yang benar-benar dapat mengacaukan beberapa hal dengan menimpa file. Ini kembali ke [[ menjadi bawaan. Jika [(tes) adalah program eksternal Shell harus membuat pengecualian dalam cara mengevaluasi < dan > hanya jika /bin/test sedang dipanggil, yang tidak akan masuk akal.
325
Kyle Brandt

Pendeknya:

[adalah bash Builtin

[[]] adalah bash Kata kunci

Kata kunci: Kata kunci sangat mirip dengan 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 untuk mengarahkan ulang 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

138
abhiomkar

Perbedaan perilaku

Beberapa perbedaan pada Bash 4.3.11:

  • Ekstensi POSIX vs Bash:

  • perintah reguler vs sihir

    • [ Hanyalah perintah biasa dengan nama yang aneh.

      ] Hanyalah argumen dari [ Yang mencegah argumen lebih lanjut dari yang digunakan.

      Ubuntu 16.04 sebenarnya memiliki executable di /usr/bin/[ Yang 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 dari \, Dan ekspansi kata terjadi seperti biasa.

    • [[ X ]] Adalah satu konstruksi yang membuat X diuraikan secara ajaib. <, &&, || Dan () Diperlakukan secara khusus, dan aturan pemisahan kata berbeda.

      Ada juga perbedaan lebih lanjut seperti = Dan =~.

      Di Bashese: [ Adalah perintah bawaan, dan [[ Adalah kata kunci: https://askubuntu.com/questions/445749/whats-the-difference-between -Shell-builtin-and-Shell-keyword

  • <

  • && Dan ||

    • [[ a = a && b = b ]]: True, logis dan
    • [ a = a && b = b ]: Kesalahan sintaks, && Diuraikan sebagai pemisah perintah DAN cmd1 && cmd2
    • [ a = a -a b = b ]: Setara, tetapi tidak digunakan lagi 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 ]: setara, tetapi () tidak digunakan lagi oleh POSIX
    • { [ a = a ] || [ a = b ]; } && [ a = b ] Setara POSIX5
  • Pemisahan kata dan pembuatan nama file berdasarkan ekspansi (split + glob)

    • x='a b'; [[ $x = 'a b' ]]: Benar, kutipan tidak diperlukan
    • x='a b'; [ $x = 'a b' ]: Kesalahan sintaksis, berkembang menjadi [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: Kesalahan sintaksis jika ada lebih dari satu file di direktori saat ini.
    • x='a b'; [ "$x" = 'a b' ]: Setara POSIX
  • =

    • [[ ab = a? ]]: Benar, karena memang pencocokan pola (* ? [ Ajaib). 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 dalam [ Dan [[, Tetapi == Adalah ekstensi Bash.
    • case ab in (a?) echo match; esac: Setara dengan POSIX
    • [[ ab =~ 'ab?' ]]: False4, kehilangan sihir dengan ''
    • [[ ab? =~ 'ab?' ]]: Benar
  • =~

    • [[ ab =~ ab? ]]: True, POSIX ekspresi reguler yang diperluas cocok, ? Tidak glob berkembang
    • [ a =~ a ]: Kesalahan sintaksis. 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 dengan POSIX.

Rekomendasi : selalu gunakan [].

Ada setara POSIX untuk setiap [[ ]] Konstruksi yang pernah saya lihat.

Jika Anda menggunakan [[ ]] Anda:

  • kehilangan portabilitas
  • memaksa pembaca untuk mempelajari seluk-beluk ekstensi bash yang lain. [ Hanyalah perintah biasa dengan nama yang aneh, tidak ada semantik khusus yang terlibat.

¹ Terinspirasi dari konstruksi [[...]] Yang setara di Korn Shell

² tetapi gagal untuk beberapa nilai a atau b (seperti + Atau index) dan melakukan perbandingan numerik jika a dan b terlihat seperti bilangan bulat desimal. expr "x$a" '<' "x$b" Mengatasi keduanya.

³ dan juga gagal untuk beberapa nilai a atau b seperti ! 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 grup perintah {...;} alih-alih (...) yang akan menjalankan subkulit yang tidak perlu) tidak diperlukan karena || dan && Operator shell (tidak seperti operator || dan &&[[...]] atau operator -o/-a[) memiliki jumlah yang sama hak lebih tinggi. Jadi [ a = a ] || [ a = b ] && [ a = b ] Akan setara.

Bracket Tunggal yaitu [] kompatibel dengan POSIX Shell untuk melampirkan ekspresi kondisional.

Kurung Ganda yaitu _ [[]] adalah versi yang disempurnakan (atau ekstensi) dari versi POSIX standar, ini didukung oleh bash dan shell lainnya (zsh, ksh).

Dalam bash, untuk perbandingan numerik kita menggunakan eq, ne, lt dan gt, dengan tanda kurung ganda untuk perbandingan, kita dapat menggunakan ==, !=, <, 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
6
Premraj

Berdasarkan pada bacaan cepat bagian-bagian yang relevan dari halaman manual, perbedaan utama tampaknya adalah bahwa == dan != operator cocok dengan suatu pola, bukannya string literal, dan juga bahwa ada =~ operator perbandingan regex.

4
womble