Với chức năng trợ giúp:
#!/bin/bash
to_param_list () {
declare -n outlist=$1
declare -n inhash=$2
for param in "${!inhash[@]}"; do
outlist+=( "--$param=${inhash[$param]}" )
done
}
declare -A my_vars=( ["key1"]="value1" ["key2"]="value" )
to_param_list list my_vars
my_script.sh "${list[@]}"
Lệnh cuối cùng trong đoạn script trên sẽ mở rộng tương đương với việc đã viết
my_script.sh "--key2=value" "--key1=value1"
Các to_param_list
chức năng lấy tên của một biến mảng và tên của một biến mảng kết hợp và sử dụng chúng để tạo ra hai "tên tài liệu tham khảo" các biến trong hàm (namerefs đã được giới thiệu trong bash
phiên bản 4.3). Sau đó chúng được sử dụng để điền vào biến mảng đã cho với các khóa và giá trị ở định dạng thích hợp từ mảng kết hợp.
Vòng lặp trong hàm lặp lại "${!inhash[@]}"
, đó là danh sách các khóa được trích dẫn riêng lẻ trong mảng kết hợp của bạn.
Khi hàm gọi trở lại, tập lệnh sẽ sử dụng mảng để gọi tập lệnh hoặc lệnh khác của bạn.
Chạy ở trên với
declare -A my_vars=( ["key1"]="hello world" ["key2"]="some thing" ["key3"]="* * *" )
to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"
kịch bản sẽ xuất ra
Arg: --key2=some thing
Arg: --key3=* * *
Arg: --key1=hello world
Điều này cho thấy các tùy chọn được tạo mà không cần tách từ hoặc tên tệp có hiệu lực. Nó cũng cho thấy rằng thứ tự của các khóa có thể không được giữ nguyên do việc truy cập các khóa ra khỏi một mảng kết hợp sẽ làm như vậy theo một thứ tự khá ngẫu nhiên.
Bạn thực sự không thể sử dụng thay thế lệnh một cách an toàn ở đây vì kết quả của nó sẽ là một chuỗi đơn. Nếu không được trích dẫn, chuỗi này sau đó sẽ được phân chia trên các ký tự khoảng trắng (theo mặc định), chuỗi này sẽ chia cả khóa và giá trị của mảng kết hợp của bạn. Shell cũng sẽ thực hiện tên tập tin toàn cầu trên các từ kết quả. Trích dẫn kép thay thế lệnh sẽ không giúp ích vì điều đó sẽ dẫn đến việc gọi bạn my_script.sh
bằng một đối số duy nhất .
Về vấn đề của bạn vớimakeself
:
Các makeself
kịch bản thực hiện điều này với các đối số cho kịch bản cài đặt của bạn:
SCRIPTARGS="$*"
Điều này lưu các đối số dưới dạng một chuỗi trong $SCRIPTARGS
(nối, được phân tách bằng dấu cách). Điều này sau đó được chèn vào kho lưu trữ tự giải nén. Để các tùy chọn được phân tích cú pháp chính xác khi chúng được đánh giá lại (chúng là khi chạy trình cài đặt), bạn sẽ phải cung cấp thêm một bộ dấu ngoặc kép trong các giá trị của các tham số để chúng được phân tách chính xác.
installer_param_array=( ["upgrade-from"]="'19 .2.0'" ["upgrade-to"]="'19.3.0'" )
Lưu ý rằng đây không phải là một lỗi trong mã của tôi. Đó chỉ là một tác dụng phụ của makeself
việc sản xuất mã shell dựa trên các giá trị do người dùng cung cấp.
Lý tưởng nhất là makeself
kịch bản nên viết mỗi đối số được cung cấp với một bộ trích dẫn bổ sung xung quanh chúng, nhưng nó không, có lẽ là do khó biết được tác động nào có thể có. Thay vào đó, nó để lại cho người dùng để cung cấp các báo giá thêm này.
Chạy lại bài kiểm tra của tôi từ trên cao, nhưng bây giờ với
declare -A my_vars=( ["key1"]="'hello world'" ["key2"]="'some value'" ["key3"]="'* * *'" )
to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"
sản xuất
Arg: --key2='some value'
Arg: --key3='* * *'
Arg: --key1='hello world'
Bạn có thể thấy rằng các chuỗi này , khi được đánh giá lại bởi trình bao, sẽ không bị phân tách trên các khoảng trắng.
Rõ ràng, bạn có thể sử dụng mảng kết hợp ban đầu của mình và thay vào đó thêm dấu ngoặc kép trong to_param_list
hàm bằng cách thay đổi
outlist+=( "--$param=${inhash[$param]}" )
vào
outlist+=( "--$param='${inhash[$param]}'" )
Một trong những thay đổi này đối với mã của bạn sẽ bao gồm các trích dẫn đơn trong các giá trị của các tùy chọn, do đó việc đánh giá lại các giá trị sẽ trở nên cần thiết .
my_script.sh "$(declare -p thearray)$"
. Trongmyscript.sh
bạn đọc nó vớisource /dev/stdin <<<"$1"
Sau đó bạn cóthearray
trong kịch bản của bạn. Bạn có thể có các đối số khác cùng với mảng. Bạn có thể truyền nhiều biến:my_script.sh "$(declare -p var1 var2 ...)"
trong đối số duy nhất này.