Các biến môi trường chứa các hàm là một bash hack. Zsh không có gì tương tự. Bạn có thể làm một cái gì đó tương tự với một vài dòng mã. Biến môi trường chứa chuỗi; các phiên bản cũ hơn của bash, trước khi Shellshock được phát hiện, đã lưu mã của hàm trong một biến có tên là hàm và có giá trị được () {
theo sau bởi mã của hàm }
. Bạn có thể sử dụng mã sau đây để nhập các biến với mã hóa này và thử chạy chúng với các cài đặt giống như bash. Lưu ý rằng zsh không thể mô phỏng tất cả các tính năng bash, tất cả những gì bạn có thể làm là tiến gần hơn một chút (ví dụ: để $foo
phân chia giá trị và mở rộng ký tự đại diện và tạo mảng dựa trên 0).
bash_function_preamble='
emulate -LR ksh
'
for name in ${(k)parameters}; do
[[ "-$parameters[name]-" = *-export-* ]] || continue
[[ ${(P)name} = '() {'*'}' ]] || continue
((! $+builtins[$name])) || continue
functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done
(Như Stéphane Chazelas , người phát hiện ban đầu của Shellshock, lưu ý, phiên bản trước của câu trả lời này có thể thực thi mã tùy ý vào thời điểm này nếu định nghĩa hàm bị sai. Phiên bản này không, nhưng tất nhiên ngay khi bạn thực hiện bất kỳ lệnh nào, nó có thể là một hàm được nhập từ môi trường.)
Các phiên bản Post-Shellshock của các hàm mã hóa bash trong môi trường sử dụng tên biến không hợp lệ (ví dụ BASH_FUNC_myfunc%%
). Điều này làm cho chúng khó phân tích đáng tin cậy hơn vì zsh không cung cấp giao diện để trích xuất các tên biến như vậy từ môi trường.
Tôi không khuyên bạn nên làm điều này. Dựa vào các chức năng được xuất trong các tập lệnh là một ý tưởng tồi: nó tạo ra sự phụ thuộc vô hình trong tập lệnh của bạn. Nếu bạn từng chạy tập lệnh của mình trong một môi trường không có chức năng của bạn (trên một máy khác, trong một công việc định kỳ, sau khi thay đổi các tệp khởi tạo shell của bạn, thì), tập lệnh của bạn sẽ không hoạt động nữa. Thay vào đó, lưu trữ tất cả các chức năng của bạn trong một hoặc nhiều tệp riêng biệt (đại loại như ~/lib/shell/foo.sh
) và bắt đầu tập lệnh của bạn bằng cách nhập các hàm mà nó sử dụng ( . ~/lib/shell/foo.sh
). Bằng cách này, nếu bạn sửa đổi foo.sh
, bạn có thể dễ dàng tìm kiếm tập lệnh nào đang dựa vào nó. Nếu bạn sao chép một tập lệnh, bạn có thể dễ dàng tìm ra tập tin phụ trợ nào.
Zsh (và ksh trước nó) làm cho điều này thuận tiện hơn bằng cách cung cấp cách tự động tải các hàm trong các tập lệnh nơi chúng được sử dụng. Hạn chế là bạn chỉ có thể đặt một chức năng cho mỗi tệp. Khai báo hàm dưới dạng tự động tải và đặt định nghĩa hàm vào một tệp có tên là tên của hàm. Đặt tệp này trong một thư mục được liệt kê trong $fpath
(mà bạn có thể định cấu hình thông qua FPATH
biến môi trường). Trong tập lệnh của bạn, khai báo các hàm tự động tải với autoload -U foo
.
Hơn nữa, zsh có thể biên dịch các tập lệnh, để tiết kiệm thời gian phân tích cú pháp. Gọi zcompile
để biên dịch một kịch bản. Điều này tạo ra một tập tin với .zwc
phần mở rộng. Nếu tệp này có mặt thì autoload
sẽ tải tệp đã biên dịch thay vì mã nguồn. Bạn có thể sử dụng zrecompile
hàm để (biên dịch lại) tất cả các định nghĩa hàm trong một thư mục.