首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用"${@:2}“可移植性?

如何使用"${@:2}“可移植性?
EN

Stack Overflow用户
提问于 2019-06-30 03:27:01
回答 3查看 852关注 0票数 3

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

但是使用"${*:2}"而不是"${@:2}"是胡说八道,因为做"${@:2}"并不等同于"${*:2}"作为下面的例子

代码语言:javascript
复制
#!/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}"

-->

代码语言:javascript
复制
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}"

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-30 04:00:21

问题中的上下文是不清楚的,除非你遵循这些链接。是关于以下来自shellcheck.net的建议

代码语言:javascript
复制
local _help_text="${@:2}"
                  ^––SC2124 Assigning an array to a string! Assign as array, or use * instead of @ to concatenate.

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

长答案:通常,"${@:2}"将得到除第一个参数之外的所有参数,并将每个参数作为一个单独的项("word")处理。另一方面,"${*:2}"生成一个单独的项,其中除了第一个参数外,由一个空格(或$IFS的第一个字符)分隔。

但是,在将变量赋值给普通变量的特定情况下,变量只能存储单个项,因此var="${@:2}"也将参数折叠为单个项,但它以比"${*:2}"更不一致的方式执行。为了避免这种情况,可以使用能够存储多个项的东西:数组。所以:

  • 非常糟糕:var="${@:2}"
  • 稍微不坏:var="${*:2}"
  • 更好的方法是:arrayvar=("${@:2}") (括号使它成为一个数组)

注意:要获得数组的元素,并将每个元素正确地作为一个单独的项处理,请使用"${arrayvar[@]}"。而且,并不是所有的shell都支持数组(特别是dash不支持它们),所以如果使用它们,您应该确保使用bash (#!/bin/bash#!/usr/bin/env bash)。如果您真的需要其他shell的可移植性,事情就会变得更加复杂。

票数 5
EN

Stack Overflow用户

发布于 2019-06-30 04:37:32

${@:2}${*:2}都不是可移植的,许多shell都会拒绝这两种无效的语法。如果您想要处理除第一个参数之外的所有参数,则应该使用移位来消除第一个参数。

代码语言:javascript
复制
first="${1}"
shift
echo The arguments after the first are:
for x; do echo "$x"; done

此时,第一个参数在"$first“中,位置参数向下移动。

票数 3
EN

Stack Overflow用户

发布于 2019-06-30 05:29:20

这演示了如何将所有${@}参数组合为一个没有hack ${@:1}${@:2} (实例化)的变量:

代码语言:javascript
复制
#!/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 "${@}";

-->

代码语言:javascript
复制
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调用

代码语言:javascript
复制
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};
}

-->

代码语言:javascript
复制
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
quoted arguments 1: 'last\ argument '
unquoted arguments 2: 'last\ argument '
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56822216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档