Ну, "$@"
розширюється до списку позиційних параметрів, один аргумент на позиційний параметр.
Коли ви робите:
set '' 'foo bar' $'blah\nblah'
cmd "$@"
cmd
викликається цими 3 аргументами: порожній рядок foo bar
та blah<newline>blah
. Оболонка буде викликати execve()
системний виклик приблизно так:
execve("/path/to/cmd", ["cmd", "", "foo bar", "blah\nblah"], [envvars...]);
Якщо ви хочете реконструювати командний рядок оболонки (тобто код на мові оболонки), який би відтворив той самий виклик, ви можете зробити щось на кшталт:
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 "$@"
Або zsh
, запитуючи різні типи пропозицій:
$ 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'
Або з zsh
, bash
або ksh93
(тут для bash
YMMV з іншими оболонками):
$ set '' 'foo bar' $'blah\nblah'
$ printf cmd; printf ' %q' "$@"; printf '\n'
cmd '' foo\ bar $'blah\nblah'
Ви також можете скористатися параметром xtrace оболонки, який змушує друкувати оболонку, яку він буде виконувати:
$ (PS4=; set -x; : cmd "$@")
: cmd '' 'foo bar' 'blah
blah'
Вище ми запустили команду :
no-op cmd
та параметри позиції як аргумент. Моя оболонка надрукувала їх у приємному процитованому вигляді, що підходить для повторного введення в оболонку. Не всі снаряди так роблять.
$
розширення та інших подвійних лапок. Ось чому в інших відповідях використовуються одиничні лапки, переходячи на деяку довжину для обробки одинарних лапок всередині рядка, або використовуються власні функції оболонки для створення копії рядка, що котирується.