Câu trả lời:
Nếu bạn muốn các tác dụng phụ của danh sách lệnh ảnh hưởng đến trình bao hiện tại của bạn , hãy sử dụng {...}
Nếu bạn muốn loại bỏ bất kỳ tác dụng phụ nào, hãy sử dụng(...)
Ví dụ: tôi có thể sử dụng một subshell nếu tôi:
$IFS
một vài lệnh, nhưng tôi không muốn thay đổi $IFS
toàn cầu cho trình bao hiện tạicd
ở đâu đó, nhưng tôi không muốn thay đổi $PWD
vỏ hiện tạiĐáng lưu ý rằng dấu ngoặc đơn có thể được sử dụng trong định nghĩa hàm:
sử dụng bình thường: niềng răng: cơ thể chức năng thực thi trong shell hiện tại; tác dụng phụ vẫn còn sau khi chức năng hoàn thành
$ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
$ pwd; count_tmp; pwd
/home/jackman
11
/tmp
$ echo "${#files[@]}"
11
sử dụng bất thường: dấu ngoặc đơn: cơ thể chức năng thực thi trong một lớp con; tác dụng phụ biến mất khi thoát khỏi subshell
$ cd ; unset files
$ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
$ pwd; count_tmp; pwd
/home/jackman
11
/home/jackman
$ echo "${#files[@]}"
0
local
từ khóa đi một chặng đường dài để làm sạch ô nhiễm đó.
pwd; (count_tmp); pwd;
Từ tài liệu bash chính thức :
()
( list )
Việc đặt một danh sách các lệnh giữa các dấu ngoặc đơn sẽ tạo ra một môi trường lớp con và mỗi lệnh trong danh sách sẽ được thực thi trong lớp con đó. Vì danh sách được thực thi trong một lớp con, các phép gán biến không còn hiệu lực sau khi lớp con hoàn thành.
{}
{ list; }
Đặt một danh sách các lệnh giữa các dấu ngoặc nhọn làm cho danh sách được thực thi trong bối cảnh shell hiện tại. Không có subshell được tạo ra. Danh sách dấu chấm phẩy (hoặc dòng mới) là bắt buộc.
Mã trong '{}' được thực thi trong luồng / tiến trình / môi trường hiện tại và các thay đổi được giữ nguyên, để đặt nó ngắn gọn hơn, mã được chạy trong phạm vi hiện tại.
Mã trong '()' được chạy bên trong một quy trình bash con riêng biệt bị loại bỏ sau khi thực thi. Quá trình con này thường được gọi là một vỏ con và có thể được coi là một phạm vi mới, giống như trẻ em.
Như một ví dụ, hãy xem xét ...
~ # { test_var=test }
~ # echo $test_var
test
~ # ( test_var2=test2 )
~ # echo $test_var2
~ #
Lưu ý trong ví dụ đầu tiên với '{}', biến vẫn được đặt ngay cả sau khi đóng '}', trong khi trong ví dụ với '()', biến không được đặt ngoài phạm vi của '()'.
(...)
được sử dụng để chạy mã trong shell phụ. Mã được sử dụng {...}
sẽ không được sử dụng trong lớp vỏ phụ.