如何移植使用“${@:2}”?
How to portability use "${@:2}"?
在 Allow for ${@:2} syntax in variable assignment 上,他们说我不应该使用 "${@:2}"
,因为它会破坏不同 shell 的东西,我应该改用 "${*:2}"
。
但是使用 "${*:2}"
而不是 "${@:2}"
是无稽之谈,因为 "${@:2}"
不等同于 "${*:2}"
,因为 following example:
#!/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}"
除非您点击链接,否则问题中的上下文不清楚。这是关于 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}"
会得到除第一个参数以外的所有参数,每个参数都被视为一个单独的项目 ("word")。另一方面,"${*:2}"
生成一个项目,其中除了第一个参数之外的所有参数都粘在一起,由 space 分隔(或者 $IFS
的第一个字符是什么)。
但是在您分配给普通变量的特定情况下,该变量只能存储单个项目,因此 var="${@:2}"
also 折叠参数缩小到单个项目,但它以不如 "${*:2}"
一致的方式进行。为了避免这种情况,请使用能够存储多个项目的东西:数组。所以:
- 非常糟糕:
var="${@:2}"
- 差一点:
var="${*:2}"
- 好多了:
arrayvar=("${@:2}")
(括号使它成为一个数组)
注意:要取回数组的元素,并将每个元素作为单独的项目正确处理,请使用 "${arrayvar[@]}"
。此外,并非所有 shell 都支持数组(值得注意的是,dash
不支持它们),因此如果你使用它们,你应该确保使用 bash shebang(#!/bin/bash
或 #!/usr/bin/env bash
).如果您真的需要对其他 shell 的可移植性,事情会变得 多 复杂。
${@:2}
和 ${*:2}
都不是可移植的,许多 shell 会拒绝这两种语法。如果你想处理除第一个参数之外的所有参数,你应该用 shift 去掉第一个参数。
first=""
shift
echo The arguments after the first are:
for x; do echo "$x"; done
此时第一个参数在"$first"中,位置参数向下移动一位。
这演示了如何将所有 ${@}
个参数合并到一个变量中,而不需要 hack ${@: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="";
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 '
在 Allow for ${@:2} syntax in variable assignment 上,他们说我不应该使用 "${@:2}"
,因为它会破坏不同 shell 的东西,我应该改用 "${*:2}"
。
但是使用 "${*:2}"
而不是 "${@:2}"
是无稽之谈,因为 "${@:2}"
不等同于 "${*:2}"
,因为 following example:
#!/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}"
除非您点击链接,否则问题中的上下文不清楚。这是关于 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}"
会得到除第一个参数以外的所有参数,每个参数都被视为一个单独的项目 ("word")。另一方面,"${*:2}"
生成一个项目,其中除了第一个参数之外的所有参数都粘在一起,由 space 分隔(或者 $IFS
的第一个字符是什么)。
但是在您分配给普通变量的特定情况下,该变量只能存储单个项目,因此 var="${@:2}"
also 折叠参数缩小到单个项目,但它以不如 "${*:2}"
一致的方式进行。为了避免这种情况,请使用能够存储多个项目的东西:数组。所以:
- 非常糟糕:
var="${@:2}"
- 差一点:
var="${*:2}"
- 好多了:
arrayvar=("${@:2}")
(括号使它成为一个数组)
注意:要取回数组的元素,并将每个元素作为单独的项目正确处理,请使用 "${arrayvar[@]}"
。此外,并非所有 shell 都支持数组(值得注意的是,dash
不支持它们),因此如果你使用它们,你应该确保使用 bash shebang(#!/bin/bash
或 #!/usr/bin/env bash
).如果您真的需要对其他 shell 的可移植性,事情会变得 多 复杂。
${@:2}
和 ${*:2}
都不是可移植的,许多 shell 会拒绝这两种语法。如果你想处理除第一个参数之外的所有参数,你应该用 shift 去掉第一个参数。
first=""
shift
echo The arguments after the first are:
for x; do echo "$x"; done
此时第一个参数在"$first"中,位置参数向下移动一位。
这演示了如何将所有 ${@}
个参数合并到一个变量中,而不需要 hack ${@: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="";
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 '