How to slice an array in Bash


Looking the "Array" section in the bash(1) man page, I didn't find a way to slice an array.

So I came up with this overly complicated function:


# @brief: slice a bash array
# @arg1:  output-name
# @arg2:  input-name
# @args:  seq args
# ----------------------------------------------
function slice() {
   local output=$1
   local input=$2
   shift 2
   local indexes=$(seq $*)

   local -i i
   local tmp=$(for i in $indexes 
                 do echo "$(eval echo \"\${$input[$i]}\")" 

   local IFS=$'\n'
   eval $output="( \$tmp )"

Used like this:

$ A=( foo bar "a  b c" 42 )
$ slice B A 1 2
$ echo "${B[0]}"  # bar
$ echo "${B[1]}"  # a  b c

Is there a better way to do this?

6/6/2018 10:56:41 PM

Accepted Answer

See the Parameter Expansion section in the Bash man page. A[@] returns the contents of the array, :1:2 takes a slice of length 2, starting at index 1.

A=( foo bar "a  b c" 42 )
C=("${A[@]:1}")       # slice to the end of the array
echo "${B[@]}"        # bar a  b c
echo "${B[1]}"        # a  b c
echo "${C[@]}"        # bar a  b c 42
echo "${C[@]: -2:2}"  # a  b c 42 # The space before the - is necesssary

Note that the fact that "a b c" is one array element (and that it contains an extra space) is preserved.

7/24/2018 4:35:30 PM

There is also a convenient shortcut to get all elements of the array starting with specified index. For example "${A[@]:1}" would be the "tail" of the array, that is the array without its first element.

A=( ${version//\./ } )
echo "${A[@]}"    # 4 7 1
B=( "${A[@]:1}" )
echo "${B[@]}"    # 7 1

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow