2011-01-07 66 views
9

Theo tôi biết có hai cách để tạo các biến cục bộ trong hàm bash: tạo một subshell hoặc khai báo mọi biến cục bộ.Biến cục bộ trong bash: local vs subshell

Ví dụ:

# using local 
function foo 
{ 
    local count 
    for count in $(seq 10) 
    do 
    echo $count 
    done 
} 

hoặc

# using subshell 
function foo 
{ 
    (
    for count in $(seq 10) 
    do 
     echo $count 
    done 
) 
} 

Obvisously phiên bản sử dụng subshell được đơn giản hơn để viết bởi vì bạn không cần phải quan tâm đến tuyên bố tất cả các biến địa phương (chưa kể đến (môi trường) các biến được tạo/xuất bởi các công cụ như getopts). Nhưng tôi có thể tưởng tượng rằng việc tạo ra một subshell có một chi phí.

Vậy cách tiếp cận tốt hơn là gì? Ưu/khuyết điểm là gì?

+0

, cũng chạy 'lệnh time' hơn 1000 kiểm tra và tìm thấy trên đầu, tôi nghĩ rằng nó nhỏ để không tồn tại. – Anders

Trả lời

9

Tạo vỏ con liên quan đến một fork(), do đó, nó chắc chắn có chi phí cao hơn so với biến cục bộ. Trong khi sub-shell có giá rẻ — bạn không phải lo lắng về chi phí của chúng khi bạn cần — chúng không miễn phí.

Nếu kịch bản của bạn sẽ được sử dụng nhiều và hiệu suất thực sự quan trọng (vì vậy bạn sẽ có hàng trăm người dùng chạy cùng một lúc, nhiều lần trong ngày), thì bạn có thể lo lắng về chi phí hiệu suất của sub-shell. OTOH, nếu bạn chạy nó mỗi tháng một lần và toàn bộ kịch bản chạy dưới 10 giây, có thể bạn sẽ không làm vậy.

Tuy nhiên, về mặt rõ ràng, tốt hơn là khai báo rõ ràng và khai báo các biến — nó làm giảm nguy cơ vỡ tập lệnh vì ai đó đến và nói "trình bao này rõ ràng là không cần thiết" (và nó thực sự không phải là, tôi muốn loại bỏ các sub-shell từ các chức năng của bạn).

Nhìn vào sự phát triển của tập lệnh Perl. Họ bắt đầu như là một miễn phí cho tất cả các biến tồn tại theo yêu cầu. Chúng dần dần trở nên khắt khe hơn, với phong cách bình thường bây giờ là để chiếm đoạt tất cả các biến. Ở một mức độ nào đó, hệ vỏ đã đi theo một đường dẫn tương tự — nhưng không nghiêm ngặt như Perl. Awk cũng là một nghiên cứu trường hợp thú vị; các hàm của nó sử dụng các biến toàn cục trừ khi chúng là các đối số cho hàm, dẫn đến các hàm được viết với 3 đối số hoạt động (nói) và 5 đối số không hoạt động để xác định các biến cục bộ một cách hiệu quả. Nó hơi lập dị, mặc dù nó 'hoạt động'.

0

Bây giờ, đảm bảo rằng tất cả các hàm luôn khai báo tất cả các biến là cục bộ, khá khó.

Tôi nghĩ rằng đây là rất dễ bị lỗi và thích luôn luôn sử dụng subshell chức năng:

f() (
echo "we are a subshell" 
) 

Không cần phải khai báo các biến địa phương - nhưng cũng không có cách nào để thay đổi các biến toàn cầu. Đó là GOOD theo ý kiến ​​của tôi!

Một hậu quả nữa là bạn luôn cần phải kiểm tra mã trả lại/thoát của các chức năng đó và hành động tương ứng! Điều này là do bạn không thể thoát khỏi tập lệnh của bạn từ bên trong một hàm subshell!

f() (
    echo "Trying to exit" 
    exit 1 
) 

f 
echo "Did not exit" 

Điều này sẽ không thoát khỏi tập lệnh của bạn. Bạn cần phải làm điều đó theo cách này: "Nhưng tôi có thể tưởng tượng rằng việc tạo một subshell có overhead"

f() (
    echo "Trying to exit" 
    exit 1 
) 

f || exit $? 
echo "Did not exit" 

này sẽ thoát

Các vấn đề liên quan