Reputation: 209
I would like to add elements to the beginning of an array instead of to the end. Is this possible in Bash?
Upvotes: 8
Views: 5190
Reputation: 3579
shift
and unshift
are useful to loop over a dynamic stack array
so the array can be modified inside the loop
for example, this is needed for argparse in bash (one, two, three)
to parse concatenated short options, or to read arguments from file
example with shift
and unshift
#!/usr/bin/env bash
# bash-stack-while-loop.sh
# stack allows to unshift args
stack=("$@")
stack=(-a -b -ab -c cval uval) # example
while [ ${#stack[@]} != 0 ]; do
arg="${stack[0]}"; stack=("${stack[@]:1}") # shift arg
case "$arg" in
-a) echo "arg a"; continue;;
-b) echo "arg b"; continue;;
-c) val="${stack[0]}"; stack=("${stack[@]:1}");
echo "arg c: ${val@Q}"; continue
;;
-[^-]*)
# unshift args: expand concatenated short options
# example: -vvv -> -v -v -v
pre_stack=()
for ((i=1;i<${#arg};i++)); do
#arg2="${arg:$i:1}"; echo "unshifting ${arg2@Q}"
pre_stack+=("-${arg:$i:1}")
done
stack=("${pre_stack[@]}" "${stack[@]}") # prepend args to stack
continue
;;
*) echo "unknown arg: ${arg@Q}";;
esac
done
example output
arg a
arg b
arg a
arg b
arg c: 'cval'
unknown arg: 'uval'
this answer was moved from how to shift array value in bash
Upvotes: 0
Reputation: 8406
Non-bash version: POSIX shells don't really have arrays, excepting shell parameters, (i.e. $1, $2, $3, ...),but for those parameters this should work:
set - a b c ; echo $1 $3
Output:
a c
Now add "foo" to the beginning:
set - foo "$@" ; echo $1 $3
Output:
foo b
Upvotes: 6
Reputation: 23870
If your array is contiguous, you can use the "${array[@]}"
syntax to construct a new array:
array=('a' 'b' 'c');
echo "${array[@]}"; # prints: a b c
array=('d' "${array[@]}");
echo "${array[@]}"; # prints: d a b c
As chepner mentions, the above method will collapse indices of sparse arrays:
array=([5]='b' [10]='c');
declare -p array; # prints: declare -a array='([5]="b" [10]="c")'
array=('a' "${array[@]}");
declare -p array; # prints: declare -a array='([0]="a" [1]="b" [2]="c")'
(Fun fact: PHP does that too - but then again, it's PHP :P)
If you need to work with sparse arrays, you can iterate over the indices of the array manually (${!array[@]}
) and increase them by one (with $((...+1))
):
old=([5]='b' [10]='c');
new=('a');
for i in "${!old[@]}"; do
new["$(($i+1))"]="${old[$i]}";
done;
declare -p new; # prints: declare -a new='([0]="a" [6]="b" [11]="c")'
Upvotes: 12
Reputation: 958
Yes, it is possible, see the example below:
#!/bin/bash
MyArray=(Elem1 Elem2);
echo "${MyArray[@]}"
MyArray=(Elem0 "${MyArray[@]}")
echo "${MyArray[@]}"
As per @ghoti's comment, declare -p MyArray
can be used to display the content of the array nicely. When invoked at the end of the script above, it outputs:
declare -a MyArray='([0]="Elem0" [1]="Elem1" [2]="Elem2")'
Upvotes: 4