如何移植性使用“${@:2}”?

use*_*ser 3 arrays bash shell posix shellcheck

允许变量赋值中的 ${@:2} 语法上,他们说我不应该使用,"${@:2}"因为它破坏了不同 shell 的内容,而我应该使用它"${*:2}"

但是,使用"${*:2}"的,而不是"${@:2}"完全是无稽之谈,因为这样做"${@:2}"不等同于"${*: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}"
Run Code Online (Sandbox Code Playgroud)

-->

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',
Run Code Online (Sandbox Code Playgroud)

如果我不能使用"${@:2}"正如他们所说的),我可以使用什么等价物代替?

这是原始问题处理除第一个参数(在 bash 脚本中)之外的所有参数,并且他们将参数与空格放在一起的唯一答案是使用"${@:2}"

Gor*_*son 5

除非您按照链接操作,否则问题中的上下文不清楚。它与shellcheck.net 的以下建议有关

local _help_text="${@:2}"
                  ^––SC2124 Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.
Run Code Online (Sandbox Code Playgroud)

简短回答:不要将事物列表(如参数)分配给普通变量,而是使用数组。

长答案:通常,"${@:2}"将获得除第一个参数之外的所有参数,每个参数都被视为一个单独的项目(“单词”)。"${*:2}",另一方面,产生一个由除第一个参数之外的所有参数组成的单个项目,由空格分隔(或第一个字符$IFS是什么)。

但是在您分配给普通变量的特定情况下,该变量只能存储单个项目,因此var="${@:2}" 也会将参数折叠为单个项目,但它的执行方式不如"${*:2}". 为了避免这种情况,请使用能够存储多个项目的东西:数组。所以:

  • 特别糟糕: var="${@:2}"
  • 差一点: var="${*:2}"
  • 好多了:(arrayvar=("${@:2}")括号使它成为一个数组)

注意:要取回数组的元素,将每个元素正确视为单独的项目,请使用"${arrayvar[@]}". 此外,并非所有 shell 都支持数组(特别dash是不支持它们),因此如果您使用它们,您应该确保使用 bash shebang(#!/bin/bash#!/usr/bin/env bash)。如果您真的需要可移植到其他 shell,事情就会变得更加复杂。