首页 > 解决方案 > 如何移植使用“${@:2}”?

问题描述

允许变量赋值中的 ${@:2} 语法时,他们说我不应该使用"${@:2}"它,因为它会破坏不同外壳的东西,我应该使用它"${*: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}"

-->

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}"如他们所说),我可以使用什么等价物?

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

标签: arraysbashshellposixshellcheck

解决方案


除非您按照链接,否则问题中的上下文不清楚。它与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,事情会变得复杂得多。


推荐阅读