Các không gian tên riêng biệt cho các hàm và biến trong shell POSIX


13

Trong dấu gạch ngang, các hàm và biến dường như sống trong các không gian tên riêng biệt:

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

Đây có phải là một tính năng đặc trưng của dash hay bảo đảm POSIX không?


2
Mã của bạn không thực sự chứng minh rằng fnhàm nằm trong một không gian tên riêng biệt; nếu thực hiện nó một lần đã xóa sạch định nghĩa của nó, chúng ta sẽ thấy chính xác hành vi tương tự. Bạn sẽ chỉ ra rằng hàm vẫn được xác định, ví dụ như type fnsau đó.
alexis

Câu trả lời:


13

Một sự đảm bảo :

2.9.5 Lệnh định nghĩa hàm

Hàm là tên do người dùng định nghĩa, được sử dụng như một lệnh đơn giản để gọi lệnh ghép với các tham số vị trí mới. Một hàm được định nghĩa bằng "lệnh định nghĩa hàm". [...]

Hàm được đặt tên là fname; ứng dụng phải đảm bảo rằng đó là một tên (xem Tên XBD) và đó không phải là tên của một tiện ích tích hợp đặc biệt. Việc triển khai có thể cho phép các ký tự khác trong tên hàm dưới dạng phần mở rộng. Việc thực hiện sẽ duy trì các không gian tên riêng cho các hàm và biến.


Cũng lưu ý rằng unset-v-fphải chọn giữa việc bỏ đặt biến hoặc hàm theo tên đã cho. bash(như trái ngược với hầu hết các tiện ích khác) sẽ bỏ đặt foo chức năng với unset foonếu không có foobiến (!), một hành vi được cho phép bởi POSIX. Đó là lý do tại sao trong các kịch bản POSIX đó là thực hành tốt để luôn luôn sử dụng một trong hai -vhoặc -f(và dĩ nhiên trong bashkịch bản là tốt, nhưng lưu ý rằng unsetkhông phải lúc nào bỏ đặt một biến trong bash, bashbiến Phạm vi có khá một vài vấn đề).
Stéphane Chazelas

Lưu ý rằng trong bash pre-shellshock, bạn sẽ gặp vấn đề khi xuất cả biến và hàm theo một tên đã cho, vì bash sẽ kết thúc bằng cách sử dụng cùng tên biến môi trường cho cả hai (đặt hai lần vào môi trường, một số lệnh có thể loại bỏ một trong số họ)
Stéphane Chazelas

8

Các biến và hàm nằm trong các không gian tên khác nhau trong dấu gạch ngang và điều này cũng được chỉ định bởi POSIX :

Việc thực hiện sẽ duy trì các không gian tên riêng cho các hàm và biến.

Thêm vào đó, các biến có phạm vi toàn cầu, theo mặc định. Một số shell (ví dụ bash, ksh và zsh) cung cấp localtừ khóa để khai báo các biến trong một hàm chỉ có phạm vi cục bộ.

Vì vậy, vâng, hành vi bạn đang thấy được đảm bảo bởi POSIX.

POSIX chưa được chuẩn hóa local , nhưng :

Việc mô tả các hàm trong một đề xuất ban đầu được dựa trên khái niệm rằng các hàm sẽ hoạt động giống như các tập lệnh shell thu nhỏ; nghĩa là, ngoại trừ việc chia sẻ các biến , hầu hết các thành phần của môi trường thực thi sẽ hoạt động như thể chúng là môi trường thực thi mới, [..]

[..] Các biến cục bộ trong một hàm đã được xem xét và đưa vào một đề xuất ban đầu khác (được điều khiển bởi tích hợp đặc biệt local), nhưng đã bị xóa vì chúng không phù hợp với mô hình đơn giản được phát triển cho các hàm và vì có một số ý kiến ​​phản đối một tính năng đặc biệt mới khác không phải là một phần của thực tiễn lịch sử. Việc triển khai nên bảo lưu mã định danh local(cũng như typeset, được sử dụng trong KornShell) trong trường hợp cơ chế biến cục bộ này được áp dụng trong phiên bản tương lai của tiêu chuẩn này.

(nhấn mạnh của tôi)


tro (từ cuối những năm 80) dựa trên dấu gạch ngang cũng có local, một trong những giao diện nhất quán ngoài đó (ví dụ như giao diện bị hỏng nghiêm trọng trong bash), chỉ mới gần đây (4.4) đã mượn local -(cho phạm vi cục bộ cho tùy chọn) từ tro (thực hiện phạm vi kiểu tro chỉ cho một $-biến đó). ksh và yash không có local(chỉ các biến thể pdksh mới có local), nhưng typesetthay vào đó (trong ksh93 chỉ typesetcung cấp phạm vi cục bộ (tĩnh) trong các hàm được khai báo bằng cú pháp ksh).
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.