Comment découper un tableau dans Bash

En regardant la section “Array” dans la page de manuel bash (1), je n’ai pas trouvé de moyen de découper un tableau.

J’ai donc trouvé cette fonction trop compliquée:

#!/bin/bash # @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 -ii local tmp=$(for i in $indexes do echo "$(eval echo \"\${$input[$i]}\")" done) local IFS=$'\n' eval $output="( \$tmp )" } 

Utilisé comme ceci:

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

Y a-t-il une meilleure manière de faire cela?

Reportez-vous à la section Extension des parameters de la page de man Bash. A[@] renvoie le contenu du tableau,: :1:2 prend une tranche de longueur 2, commençant à l’index 1.

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

Notez que le fait que “abc” soit un élément de tableau (et qu’il contient un espace supplémentaire) est préservé.

Il existe également un raccourci pratique pour obtenir tous les éléments du tableau en commençant par l’index spécifié. Par exemple, “$ {A [@]: 1}” serait la “queue” du tableau, c’est-à-dire le tableau sans son premier élément.

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

Array comme dans Python (à partir de la bibliothèque rebash ):

 array_slice() { local __doc__=' Returns a slice of an array (similar to Python). From the Python documentation: One way to remember how slices work is to think of the indices as pointing between elements, with the left edge of the first character numbered 0. Then the right edge of the last element of an array of length n has index n, for example: ``` +---+---+---+---+---+---+ | 0 | 1 | 2 | 3 | 4 | 5 | +---+---+---+---+---+---+ 0 1 2 3 4 5 6 -6 -5 -4 -3 -2 -1 ``` >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice 1:-2 "${a[@]}") 1 2 3 >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice 0:1 "${a[@]}") 0 >>> local a=(0 1 2 3 4 5) >>> [ -z "$(array.slice 1:1 "${a[@]}")" ] && echo empty empty >>> local a=(0 1 2 3 4 5) >>> [ -z "$(array.slice 2:1 "${a[@]}")" ] && echo empty empty >>> local a=(0 1 2 3 4 5) >>> [ -z "$(array.slice -2:-3 "${a[@]}")" ] && echo empty empty >>> [ -z "$(array.slice -2:-2 "${a[@]}")" ] && echo empty empty Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the ssortingng being sliced. >>> local a=(0 1 2 3 4 5) >>> # from the beginning to position 2 (excluded) >>> echo $(array.slice 0:2 "${a[@]}") >>> echo $(array.slice :2 "${a[@]}") 0 1 0 1 >>> local a=(0 1 2 3 4 5) >>> # from position 3 (included) to the end >>> echo $(array.slice 3:"${#a[@]}" "${a[@]}") >>> echo $(array.slice 3: "${a[@]}") 3 4 5 3 4 5 >>> local a=(0 1 2 3 4 5) >>> # from the second-last (included) to the end >>> echo $(array.slice -2:"${#a[@]}" "${a[@]}") >>> echo $(array.slice -2: "${a[@]}") 4 5 4 5 >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice -4:-2 "${a[@]}") 2 3 If no range is given, it works like normal array indices. >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice -1 "${a[@]}") 5 >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice -2 "${a[@]}") 4 >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice 0 "${a[@]}") 0 >>> local a=(0 1 2 3 4 5) >>> echo $(array.slice 1 "${a[@]}") 1 >>> local a=(0 1 2 3 4 5) >>> array.slice 6 "${a[@]}"; echo $? 1 >>> local a=(0 1 2 3 4 5) >>> array.slice -7 "${a[@]}"; echo $? 1 ' local start end array_length length if [[ $1 == *:* ]]; then IFS=":"; read -r start end <<<"$1" shift array_length="$#" # defaults [ -z "$end" ] && end=$array_length [ -z "$start" ] && start=0 (( start < 0 )) && let "start=(( array_length + start ))" (( end < 0 )) && let "end=(( array_length + end ))" else start="$1" shift array_length="$#" (( start < 0 )) && let "start=(( array_length + start ))" let "end=(( start + 1 ))" fi let "length=(( end - start ))" (( start < 0 )) && return 1 # check bounds (( length < 0 )) && return 1 (( start < 0 )) && return 1 (( start >= array_length )) && return 1 # parameters start with $1, so add 1 to $start let "start=(( start + 1 ))" echo "${@: $start:$length}" } alias array.slice="array_slice" 

Disons que je lis un tableau de l’utilisateur, alors je veux voir les éléments 3 à 7 inclus.

 cnt=0 while read var; do myarr[cnt]=$var cnt=$((cnt+1)) done echo ${myarr[@]:3:5}