Tôi đã viết một kịch bản có thể tạo ra các đối số đó cho tôi, với các trích dẫn
Nếu đầu ra được trích dẫn chính xác cho shell và bạn tin tưởng đầu ra , thì bạn có thể chạy eval
trên nó.
Giả sử bạn có một shell hỗ trợ các mảng, tốt nhất nên sử dụng một shell để lưu trữ các đối số bạn nhận được.
Nếu ./gen_args.sh
tạo đầu ra như thế 'foo bar' '*' asdf
, thì chúng ta có thể chạy eval "args=( $(./gen_args.sh) )"
để điền vào một mảng được gọi args
với kết quả. Đó sẽ là ba yếu tố foo bar
, *
, asdf
.
Chúng ta có thể sử dụng "${args[@]}"
như bình thường để mở rộng các thành phần mảng riêng lẻ:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Lưu ý các trích dẫn. "${array[@]}"
Mở rộng cho tất cả các thành phần dưới dạng các đối số riêng biệt không được sửa đổi. Không có dấu ngoặc kép, các thành phần mảng có thể bị tách từ. Xem ví dụ trang Mảng trên BashGuide .)
Tuy nhiên , eval
sẽ vui vẻ chạy bất kỳ thay thế shell nào, vì vậy $HOME
trong đầu ra sẽ mở rộng sang thư mục chính của bạn và một sự thay thế lệnh sẽ thực sự chạy một lệnh trong shell đang chạy eval
. Một đầu ra của "$(date >&2)"
sẽ tạo ra một phần tử mảng trống duy nhất và in ngày hiện tại trên thiết bị xuất chuẩn. Đây là một mối quan tâm nếu gen_args.sh
lấy dữ liệu từ một số nguồn không đáng tin cậy, như một máy chủ khác qua mạng, tên tệp được tạo bởi người dùng khác. Đầu ra có thể bao gồm các lệnh tùy ý. (Nếu get_args.sh
bản thân nó là độc hại, nó sẽ không cần xuất bất cứ thứ gì, nó chỉ có thể chạy các lệnh độc hại trực tiếp.)
Một cách khác để trích dẫn shell, khó phân tích mà không có eval, sẽ là sử dụng một số ký tự khác làm dấu phân cách trong đầu ra của tập lệnh của bạn. Bạn cần chọn một thứ không cần thiết trong các đối số thực tế.
Hãy chọn #
và có đầu ra kịch bản foo bar#*#asdf
. Bây giờ chúng ta có thể sử dụng mở rộng lệnh không trích dẫn để phân chia đầu ra của lệnh cho các đối số.
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
Bạn sẽ cần thiết lập IFS
lại sau nếu bạn phụ thuộc vào phân tách từ ở nơi khác trong tập lệnh ( unset IFS
nên hoạt động để biến nó thành mặc định) và cũng có thể sử dụng set +f
nếu bạn muốn sử dụng Globing sau này.
Nếu bạn không sử dụng Bash hoặc một số shell khác có mảng, bạn có thể sử dụng các tham số vị trí cho điều đó. Thay thế args=( $(...) )
bằng set -- $(./gen_args.sh)
và sử dụng "$@"
thay vì "${args[@]}"
sau đó. (Ở đây cũng vậy, bạn cần trích dẫn xung quanh "$@"
, nếu không các tham số vị trí có thể bị chia tách từ.)
eval
thể có thể được sử dụng, nhưng nó thường không được khuyến khích.xargs
cũng là một cái gì đó để xem xét