问题
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, onlyeval
the assignment given above in example and nothing more (this necessitates the temporary variableparam
). Of course, sanity check ofpos
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