Vâng, "$@"
mở rộng đến danh sách các tham số vị trí, một đối số cho mỗi tham số vị trí.
Khi bạn làm:
set '' 'foo bar' $'blah\nblah'
cmd "$@"
cmd
đang được gọi với 3 đối số đó: chuỗi rỗng foo bar
và blah<newline>blah
. Shell sẽ gọi cuộc gọi execve()
hệ thống với một cái gì đó như:
execve("/path/to/cmd", ["cmd", "", "foo bar", "blah\nblah"], [envvars...]);
Nếu bạn muốn xây dựng lại một dòng lệnh shell (đó là mã trong ngôn ngữ shell) sẽ tái tạo cùng một lời gọi đó, bạn có thể làm một cái gì đó như:
awk -v q="'" '
function shellquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
for (i = 1; i < ARGC; i++) {
printf "%s", sep shellquote(ARGV[i])
sep = " "
}
printf "\n"
}' cmd "$@"
Hoặc với zsh
, yêu cầu các loại báo giá khác nhau:
$ set '' 'foo bar' $'blah\nblah'
$ print -r -- cmd "${(q)@}"
cmd '' foo\ bar blah$'\n'blah
$ print -r -- cmd "${(qq)@}"
cmd '' 'foo bar' 'blah
blah'
$ print -r -- cmd "${(qqq)@}"
cmd "" "foo bar" "blah
blah"
$ print -r -- cmd "${(qqqq)@}"
cmd $'' $'foo bar' $'blah\nblah'
Hoặc với zsh
, bash
hoặc ksh93
(ở đây bash
, YMMV với các shell khác):
$ set '' 'foo bar' $'blah\nblah'
$ printf cmd; printf ' %q' "$@"; printf '\n'
cmd '' foo\ bar $'blah\nblah'
Bạn cũng có thể sử dụng tùy chọn xtrace của shell khiến shell in ra những gì nó sẽ thực thi:
$ (PS4=; set -x; : cmd "$@")
: cmd '' 'foo bar' 'blah
blah'
Ở trên, chúng tôi đã chạy lệnh :
no-op với cmd
và các tham số vị trí làm đối số. Vỏ của tôi đã in chúng theo kiểu trích dẫn đẹp phù hợp để tái tạo vỏ. Không phải tất cả các vỏ làm điều đó.
$
mở rộng và trích dẫn kép khác. Đó là lý do tại sao các câu trả lời khác sử dụng các trích dẫn đơn trong khi đi đến một số độ dài để xử lý các trích dẫn đơn bên trong chuỗi hoặc sử dụng các tính năng riêng của shell để tạo ra một bản sao được trích dẫn của chuỗi.