Kapan menggunakan () vs. {} di bash?

74

Saya sedang mempelajari skrip shell dengan bash dan saya perlu tahu perbedaan antara (...)dan {...}. Bagaimana seseorang memilih di antara keduanya saat menulis skrip?

Pikiran Gemuk
sumber
1
Lihat wiki.bash-hackers.org
Helio
3
Maksud Anda hanya dalam konteks pengelompokan perintah?
heemayl

Jawaban:

87

Jika Anda ingin efek samping dari daftar perintah mempengaruhi shell Anda saat ini , gunakan {...}
Jika Anda ingin membuang efek samping, gunakan(...)

Misalnya, saya mungkin menggunakan subkulit jika saya:

  • ingin mengubah $IFSbeberapa perintah, tapi saya tidak ingin mengubah $IFSsecara global untuk shell saat ini
  • cdsuatu tempat, tetapi saya tidak ingin mengubah $PWDuntuk shell saat ini

Penting untuk dicatat bahwa tanda kurung dapat digunakan dalam definisi fungsi:

  • penggunaan normal: kawat gigi: fungsi tubuh dijalankan di shell saat ini; efek samping tetap ada setelah fungsi selesai

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • penggunaan yang tidak biasa: tanda kurung: fungsi tubuh dijalankan dalam sebuah subkulit; efek samping menghilang ketika subkulit keluar

    $ cd ; unset files
    $ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /home/jackman
    $ echo "${#files[@]}"
    0
    

Dokumentasi

glenn jackman
sumber
11
Setelah bertahun-tahun pengembangan shell saya tidak tahu Anda bisa menggunakan tanda kurung untuk menjalankan fungsi dalam subkulit. Ide yang sangat bagus untuk menghindari polusi namespace global!
l0b0
7
Menggunakan localkata kunci berjalan jauh untuk membersihkan polusi itu.
glenn jackman
2
Ya, tetapi Anda harus ingat untuk mendeklarasikan setiap variabel lokal, dan itu mengacaukan kode.
l0b0
4
Petunjuk: Jika Anda ingin fungsi bebas efek samping tetapi hindari sintaks deklarasi fungsi yang tidak biasa (yang mungkin tidak disadari oleh editor kode) maka gunakan tanda kurung pada pemanggilan fungsi alih-alih deklarasi:pwd; (count_tmp); pwd;
Juve
2
ke shell ... foo () (:;) setara dengan foo () {(:;); } Itulah yang dilaporkannya jika Anda bertanya!
anthony
23

Dari dokumentasi resmi bash :

()

( list )

Menempatkan daftar perintah di antara tanda kurung menyebabkan lingkungan subkulit dibuat, dan masing-masing perintah dalam daftar dieksekusi di subkulit itu. Karena daftar dieksekusi dalam subkulit, tugas variabel tidak tetap berlaku setelah subkulit selesai.

{}

{ list; }

Menempatkan daftar perintah antara kurung kurawal menyebabkan daftar dieksekusi dalam konteks shell saat ini. Tidak ada subkulit yang dibuat. Tanda titik koma (atau baris baru) diperlukan.

Trauma Digital
sumber
9

Kode dalam '{}' dieksekusi di utas / proses / lingkungan saat ini dan perubahan dipertahankan, agar lebih ringkas, kode dijalankan dalam cakupan saat ini.
Kode di '()' dijalankan di dalam proses bash anak terpisah yang dibuang setelah eksekusi. Proses anak ini sering disebut sebagai sub-shell dan dapat dianggap sebagai ruang lingkup baru seperti anak.

Sebagai contoh pertimbangkan hal berikut ...

 ~ # { test_var=test }
 ~ # echo $test_var
 test
 ~ # ( test_var2=test2 )
 ~ # echo $test_var2

 ~ # 

Perhatikan pada contoh pertama dengan '{}' variabel masih disetel bahkan setelah penutupan '}', sedangkan dalam contoh dengan '()' variabel tidak disetel di luar ruang lingkup '()'.

merokok2345
sumber
4

(...)digunakan untuk menjalankan kode dalam sub-shell. Kode yang digunakan antara kami {...}tidak akan digunakan dalam sub-shell.

Antoine Orsoni
sumber