8

I would like to add elements to the beginning of an array instead of to the end. Is this possible in Bash?

1
  • 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. Commented Aug 15, 2016 at 16:42

4 Answers 4

12

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")'
Sign up to request clarification or add additional context in comments.

Comments

6

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

Comments

4

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

You may find that declare -p MyArray is a useful way of visualizing the contents of your array.
...or at least printf '%q\n' "${MyArray[@]}" -- with echo "${MyArray[@]}", you can't tell the difference between MyArray=( hello world ) and MyArray=( "hello world" )
1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.