Access bash positional parameter through variable

断了今生、忘了曾经 提交于 2021-02-16 09:17:25

问题


How to access bash positional parameter through a variable? e.g. I have a variable "pos", which can be anything between 1 to 6 (say).

If pos==1, I want to do: echo $1

If pos==2, I want to do: echo $2

So on.

Intuitively, I want to do something like: echo $$pos. I want to do it in one line.


回答1:


Use variable indirection:

echo "${!pos}"



回答2:


Here are several solutions. Some may need a recent version of bash, others may still work with a very old one.

Let us set up first our environment...

$ set first second third fourth
$ pos=3

Substring expansion

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

This is very flexible:

  • Can match several consecutive parameters: "${@:pos:2}"

  • Can match all the remaining parameters starting from pos: "${@:pos}"

  • Works with literals, variable pos is not necessary: "${@:3:2}"

  • Works also with any arithmetic expression: "${@:(pos-1)*2:1}"

  • Works also with negative numbers (counts down from the last):

$ 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

Intermediary array

Bash's arrays are very flexible. Just put your script parameters into an array and access its elements with pos:

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

Advantages:

  • Straightforward array notation array[pos]
  • Array index may be negative (counting down from the last element)
  • Array index may be any arithmetic expression: "${args[(pos-1)*2]}"
  • Can be combined with substring expansion, so all its advantages apply here too: "${args[@]:pos:2}"

Indirect expansion

The ${!var} syntax fetches the content of var and the whole is substituted with $content. If var contains a number n, the whole is substituted with the nth positional parameter.

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

Drawbacks:

  • Less flexible than above solutions

eval

Father of all evils, eval may still be useful if you shell doesn't support any of the above:

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

Advantages:

  • Works in any Bourne shell
  • Flexibility: with eval you can do anything (and this is also the problem with it)

Drawbacks:

  • eval is a beast that is difficult to tame. Limit its use to the strict minimum. For example, only eval the assignment given above in example and nothing more (this necessitates the temporary variable param). Of course, sanity check of pos is mandatory but this is also the case for the other commands given here.

Subshell

Since subshells inherit the positional parameters, and since what happens in subshells stays in subshells, we can use these properties to shift the parameters:

$ 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

Advantages:

  • Works in any Bourne shell
  • Arithmetic operations on pos


来源:https://stackoverflow.com/questions/29015943/access-bash-positional-parameter-through-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!