通过变量访问bash位置参数

时间:2015-03-12 17:02:55

标签: linux bash shell unix

如何通过变量访问bash位置参数? 例如我有一个变量" pos",可以是1到6之间的任何东西(比方说)。

如果pos==1,我想这样做:echo $1

如果pos==2,我想这样做:echo $2

等等。

直观地说,我想做一些事情:echo $$pos。 我想在一行中做到这一点。

2 个答案:

答案 0 :(得分:1)

使用变量间接:

echo "${!pos}"

答案 1 :(得分:1)

这里有几个解决方案。有些人可能需要最新版本的 bash,其他人可能仍然使用非常旧的版本。

让我们先设置我们的环境...

$ set first second third fourth
$ pos=3

子串扩展

$ printf 'Parameter %d is "%s"\n' "$pos" "${@:pos:1}"
Parameter 3 is "third"

这非常灵活:

  • 可以匹配多个连续参数:"${@:pos:2}"

  • 可以匹配从pos开始的所有剩余参数:"${@:pos}"

  • 使用文字,不需要变量 pos"${@:3:2}"

  • 也适用于任何算术表达式:"${@:(pos-1)*2:1}"

  • 也适用于负数(从最后一个倒数):

$ printf 'Last parameter is "%s"\n' "${@: -1}"    # Mind the space!
Last parameter is "fourth"
$ printf 'Parameter %d is "%s" to last\n' "$pos" "${@: -pos:1}"
Parameter 3 is "second" to last

中间数组

Bash 的数组非常灵活。只需将您的脚本参数放入一个数组并使用 pos 访问其元素:

$ args=( "$0" "$@" )
$ printf 'Parameter %d is "%s"\n' "$pos" "${args[pos]}"

优点:

  • 简单的数组符号array[pos]
  • 数组索引可能为负数(从最后一个元素开始倒数)
  • 数组索引可以是任何算术表达式:"${args[(pos-1)*2]}"
  • 可以与子字符串扩展结合使用,因此它的所有优点也适用于此:"${args[@]:pos:2}"

间接扩张

${!var} 语法获取 var 的内容,并将整个内容替换为 $content。如果 var 包含数字 n,则将整个替换为第 n 个位置参数。

$ printf 'Parameter %d is "%s"\n' "$pos" "${!pos}"
Parameter 3 is "third"

缺点:

  • 不如上述解决方案灵活

评估

万恶之父,如果您的 shell 不支持上述任何一项,eval 可能仍然有用:

$ eval "param=\${$pos}"     # Just eval the assignment, nothing more
$ printf 'Parameter %d is "%s"\n' "$pos" "$param"
Parameter 3 is "third"

优点:

  • 适用于任何 Bourne shell
  • 灵活性:使用 eval,您可以做任何事情(这也是它的问题)

缺点:

  • eval 是一种难以驯服的野兽。将其使用限制在严格的最低限度。例如,只有 eval 上面示例中给出的赋值,仅此而已(这需要临时变量 param)。当然,pos 的健全性检查是强制性的,但此处给出的其他命令也是如此。

子外壳

由于子shell继承了位置参数,并且由于子shell中发生的事情保留在子shell中,我们可以使用这些属性来移动参数:

$ printf 'Parameter %d is "%s"\n' "$pos" "$(shift $((pos-1)); printf %s "$1")"
Parameter 3 is "third"
$ echo "$1"   # Check that parameters weren't shifted in parent shell
first

优点:

  • 适用于任何 Bourne shell
  • pos 上的算术运算