在Allow for ${@:2} syntax in variable assignment上,他们说我不应该使用"${@:2}"
,因为它会破坏不同的外壳,而我应该使用"${*:2}"
。
但是用"${*:2}"
代替"${@:2}"
是无意义的,因为这样做"${@:2}"
不等同于following example的"${*:2}"
:
#!/bin/bash
check_args() {
echo "\$#=$#"
local counter=0
for var in "$@"
do
counter=$((counter+1));
printf "$counter. '$var', ";
done
printf "\\n\\n"
}
# setting arguments
set -- "space1 notspace" "space2 notspace" "lastargument"; counter=1
echo $counter': ---------------- "$*"'; counter=$((counter+1))
check_args "$*"
echo $counter': ---------------- "${*:2}"'; counter=$((counter+1))
check_args "${*:2}"
echo $counter': ---------------- "${@:2}"'; counter=$((counter+1))
check_args "${@:2}"
->
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
1: ---------------- "$*"
$#=1
1. 'space1 notspace space2 notspace lastargument',
2: ---------------- "${*:2}"
$#=1
1. 'space2 notspace lastargument',
3: ---------------- "${@:2}"
$#=2
1. 'space2 notspace', 2. 'lastargument',
如果我不能使用"${@:2}"
(as they say),可以使用什么等效项?
这是原始问题Process all arguments except the first one (in a bash script),将参数和空格保持在一起的唯一答案是使用"${@:2}"
答案 0 :(得分:4)
除非您点击链接,否则问题中的上下文并不清楚。与the following recommendation from shellcheck.net有关:
local _help_text="${@:2}"
^––SC2124 Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.
简短的回答:不要将事物列表(例如参数)分配给简单变量,而应使用数组。
长答案:通常,"${@:2}"
将获得除第一个参数以外的所有参数,每个参数都被视为一个单独的项目(“单词”)。另一方面,"${*:2}"
会产生单个项目,其中除了第一个参数之外,所有其他参数都粘结在一起,并用空格(或$IFS
的第一个字符不管)分隔。
但是在特定情况下,您要分配给一个普通变量,该变量只能存储单个项目,因此var="${@:2}"
还将参数折叠为单个项,但与"${*:2}"
不一致。为了避免这种情况,请使用能够存储多个项目的东西:数组。所以:
var="${@:2}"
var="${*:2}"
arrayvar=("${@:2}")
(括号使它成为数组)注意:要取回数组的元素(将每个元素都正确地视为一个单独的项目),请使用"${arrayvar[@]}"
。另外,并非所有shell都支持数组(特别是dash
不支持数组),因此,如果使用它们,则应确保使用bash shebang(#!/bin/bash
或#!/usr/bin/env bash
)。如果您确实需要可移植到其他Shell,则事情变得更加复杂。
答案 1 :(得分:3)
${@:2}
和${*:2}
都不是可移植的,并且许多shell都将两者都视为无效语法。如果要处理除第一个参数以外的所有参数,则应移开第一个参数。
first="${1}"
shift
echo The arguments after the first are:
for x; do echo "$x"; done
此时,第一个参数在“ $ first”中,并且位置参数向下移动一个。
答案 2 :(得分:0)
这演示了如何将所有${@}
自变量组合为一个变量,而不会被${@:1}
或${@:2}
(live example)破坏:
#!/bin/bash
function get_all_arguments_as_single_one_unquoted() {
single_argument="$(printf "%s " "${@}")";
printf "unquoted arguments %s: '%s'\\n" "${#}" "${single_argument}";
}
function get_all_arguments_as_single_one_quoted() {
single_argument="${1}";
printf "quoted arguments %s: '%s'\\n" "${#}" "${single_argument}";
}
function escape_arguments() {
escaped_arguments="$(printf '%q ' "${@}")";
get_all_arguments_as_single_one_quoted "${escaped_arguments}";
get_all_arguments_as_single_one_unquoted ${escaped_arguments};
}
set -- "first argument" "last argument";
escape_arguments "${@}";
-->
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
quoted arguments 1: 'first\ argument last\ argument '
unquoted arguments 4: 'first\ argument last\ argument '
正如@William Pursell所指出的那样,如果您只想获取{@:2}
参数,则可以在shift
之前添加一个"${@}"
调用
function escape_arguments() {
shift;
escaped_arguments="$(printf '%q ' "${@}")";
get_all_arguments_as_single_one_quoted "${escaped_arguments}";
get_all_arguments_as_single_one_unquoted ${escaped_arguments};
}
-->
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
quoted arguments 1: 'last\ argument '
unquoted arguments 2: 'last\ argument '