En regardant la section "Array" de la page de manuel bash (1), je n'ai pas trouvé de moyen de découper un tableau.
Je suis donc venu avec 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 -i i
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 "a b c" 42 )
$ slice B A 1 2
$ echo "${B[0]}" # bar
$ echo "${B[1]}" # a b c
Y a-t-il une meilleure manière de faire cela?
Réponses:
Consultez la section Extension des paramètres de la
man
page Bash .A[@]
renvoie le contenu du tableau,:1:2
prend une tranche de longueur 2, en commençant à l'index 1.A=( foo bar "a b c" 42 ) B=("${A[@]:1:2}") 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
Notez que le fait que "ab c" soit un élément du tableau (et qu'il contienne un espace supplémentaire) est conservé.
la source
idx=(${!A[@]}); echo ${idx[@]:1}
.${@:1:2}
$@
en un tableau approprié avant de faire cela, sinon les arguments contenant des espaces seraient divisés:ARGS=( "$@" ); ARGS_AFTER_FIRST=( "${ARGS[@]:1}" )
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
la source
echo "${A[@]::1}" # 4
"${${@}[@]:1}"
.${@:2}
marche bien.Tranche de tableau comme en 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 string 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"
la source
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}
la source