Нет, это не эквивалентно, потому что слова разделены.Ex.следующий код:
check_args() {
echo "\$#=$#"
printf "%s\n" "$@";
}
# setting arguments
set -- "space notspace" "newline"$'\n'"newline"
echo '1: ---------------- "$*"'
check_args "$*"
echo '2: ---------------- $(printf '\''%q '\'' "${@:1}")'
check_args $(printf '%q ' "${@:1}")
echo '3: ---------------- "$(printf '\''%q '\'' "${@:1}")"'
check_args "$(printf '%q ' "${@:1}")"
echo '4: ---------------- IFS=@ and "$*"'
( IFS=@; check_args "$*"; )
echo "5: ---------------- duplicating quoted"
check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"
echo "6: ---------------- duplicating quoted IFS=@"
( IFS=@; check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"; )
echo "7: ---------------- duplicating eval unquoted"
eval check_args $(printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/'"${IFS:0:1}"'$//')
echo "8: ---------------- duplicating eval unquoted IFS=@"
( eval check_args $(IFS=@ ; printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/"'"${IFS:0:1}"'"$//'); )
выведет:
1: ---------------- "$*"
$#=1
space notspace newline
newline
2: ---------------- $(printf '%q ' "${@:1}")
$#=3
space\
notspace
$'newline\nnewline'
3: ---------------- "$(printf '%q ' "${@:1}")"
$#=1
space\ notspace $'newline\nnewline'
4: ---------------- IFS=@ and "$*"
$#=1
space notspace@newline
newline
5: ---------------- duplicating quoted
$#=1
space notspace newline
newline
6: ---------------- duplicating quoted IFS=@
$#=1
space notspace@newline
newline
7: ---------------- duplicating eval unquoted
$#=1
space notspace newline
newline
8: ---------------- duplicating eval unquoted IFS=@
$#=1
space notspace@newline
newline
проверено на repl .
"$*"
выводит аргументы, разделенные наМФС.Таким образом, как показано в тесте 4
, если разделитель не сброшен или не установлен на пробел, то результат $*
будет делимеризован IFS, @
в этом примере.
Также, если IFS не установлен или установлен в пробел, вывод $*
не включает в себя завершающий пробел, в то время как printf '%q '
всегда будет печатать завершающий пробел в конце строки.
Вывод $(printf '%q ' "${@:1}")
все еще разделен на пробел.Таким образом, контрольный пример 2
получает 3 аргумента, потому что строка space notspace
разделена пробелом и разделена на два аргумента.При вложении printf
внутрь "
не поможет - printf
подставляет ex.символы новой строки для \n
символов.
Случаи 5
, 6
, 7
, 8
- мои попытки повторить поведение "$*"
с использованием printf.Это можно видеть в случаях 7
и 8
, которые я использовал eval
, в случаях 5
и 6
я цитировал подстановку команд.Выходные данные случаев (5
и 6
) и (7
и 8
) должны соответствовать выходным данным случаев 1
и 4
соответственно.
Для дублирования поведения "$*"
Особое внимание необходимо уделить IFS
, чтобы правильно разделить струны.Я использовал sed 's/'"${IFS:0:1}"'$//'
, чтобы удалить конечный разделитель IFS из вывода printf
.Случаи 5
и 6
без кавычек $(printf ...)
попытки, с 6
с использованием IFS=@
, чтобы показать разделительные работы.Случаи 7
и 8
используют eval со специальной обработкой для IFS
, потому что сам символ IFS
должен быть заключен в кавычки, чтобы оболочка больше не разбивалась на него, поэтому printf '%q"'"${IFS:0:1}"'"'
.
выполнение $ (printf '% q' "$ {@: 2}") (обратите внимание на 2 вместо 1, как раньше) невозможно с чистым bash $ *?
Возможно, вы могли бы просто переместить аргументы внутри подстановки $(shift; printf "%s\n" "$*")
, но, как показано выше, они в любом случае не эквивалентны.