I would like to add elements to the beginning of an array instead of to the end. Is this possible in Bash?
-
You can hack a quick array reassignment at the beginning or end of the array, but there's nothing in bash that will insert an index. Why don't you try writing a function to rewrite the array, and if you have trouble, ask for help on StackOverflow? Most of us are happy to help you fix your code, but generally are not willing to act as unpaid short order programming staff.ghoti– ghoti2016-08-15 16:42:10 +00:00Commented Aug 15, 2016 at 16:42
4 Answers
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")'
Comments
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")'
2 Comments
declare -p MyArray is a useful way of visualizing the contents of your array.printf '%q\n' "${MyArray[@]}" -- with echo "${MyArray[@]}", you can't tell the difference between MyArray=( hello world ) and MyArray=( "hello world" )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