I am trying to have a bash script that has some args. One of them needs to be an array so the number of args is not fixed in that array.
So I want to run my bash script as follows:
test.sh arg1 arg2 arr1
Inside test.sh, I'm doing something like
arg1=$1
arg2=$2
arr=$3 # arr1
for var in len(arr)
do
# do something
done
#!/bin/bash
arg1=$1
arg2=$2
shift 2
for argn do
# do something with "$argn"
done
That is, receive the two fixed arguments first, then shift these off the list of positional argument using shift 2
. What's left in the list of positional arguments is the variable length list of other arguments.
That last loop can be written
for argn in "$@"; do
# do something with "$argn"
done
... but make sure that you use "$@"
and not just $@
as that would split the individual arguments on whitespaces and invoke filename globbing.
Your method of passing to the script is valid. You could rewrite your script as
#!/bin/bash
arg1=$1
arg2=$2
for i in $(seq 3 $#); do
#reference each thing in arr1 with ${!i}
done
Though that's admittedly hard to read. {!var}
is indirection (basically, you ask what for what i
is equal to, and then you ask for whatever that is equal to, so if i=1
, you're doing ${!i}
is the same as $1
).
This doesn't keep the array together, though. If you needed arr1
to stay arr1
in the script, you could do:
#!/bin/bash
arg1=$1
shift
arg2=$1
shift
arr1=("$@")
Bash takes command-line arguments by their position relative to the script name (which gets the variable $0
). For your scenario, arg1
is $1
, arg2
is $2
, and arr1
is $3 $4 $5 ...
, depending on the length of your array. shift
will move all the arguments down 1, making 1=$2
, 2=$3
, etc. for all the arguments you have. (It doesn't change $0
from the script name; that stays the same.)
$@
grabs ALL the command-line variables, starting at $1
. However, because we shifted away the variables for arg1
and arg2
, grabbing all the variables really means that we're only grabbing the variables that were originally part of our array.
If you have multiple arrays, or the array is first in the list, then you have to know how many elements are in the array for it to work. Let's say you wanted to do test.sh arr1 var1 arr2
, and you knew both arrays were length 3:
#!/bin/bash
arr1=("${@:1:4}")
shift ${#arr1[@]} #shift by the length of arr1
arg1=$1
shift
arr2=("$@")
Hopefully you can see how this could work with a variable number of elements in the array, by passing the length of the array first, grabbing that with size=$(( 1 + $1 ))
, then shift
ing and grabbing the array with ${@:1:$size}
and then doing ((size--))
and shift $size
to start again with the next array size and array.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.