Как разрезать массив в Bash
Глядя на раздел «Массив» на странице man bash (1), я не нашел способ срезать массив.
Поэтому я придумал эту чрезмерно сложную функцию:
#!/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 )" }
Используется следующим образом:
- Как распечатать уникальные элементы в массиве Perl?
- Привязать к переменной массива bash косвенно, динамически сконструированным именем переменной
- Где задано свойство длины массива?
- Объявить массив const
- Является ли это указателем на указатель начала массива?
$ A=( foo bar "abc" 42 ) $ slice BA 1 2 $ echo "${B[0]}" # bar $ echo "${B[1]}" # abc
Есть лучший способ сделать это?
- Глубокая копия массива объектов
- массив фиксированной длины typedef
- Можете ли вы resize массива C ++ после инициализации?
- Как определить, инициализирован ли массив в VB6?
- Перечислить дубликаты массивов со счетом
- Разница между JSONObject и JSONArray
- Проверьте, содержит ли строка значение в массиве
- Как передать массив Scala в метод Scala vararg?
См. Раздел « Расширение параметров » на странице управления Bash. A[@]
возвращает содержимое массива :1:2
принимает срез длиной 2, начиная с индекса 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
Обратите внимание, что факт, что «abc» является одним элементом массива (и содержит лишнее пространство), сохраняется.
Существует также удобный ярлык для получения всех элементов массива, начиная с указанного индекса. Например, «$ {A [@]: 1}” будет «хвостом» массива, то есть массивом без его первого элемента.
version=4.7.1 A=( ${version//\./ } ) echo "${A[@]}" # 4 7 1 B=( "${A[@]:1}" ) echo "${B[@]}" # 7 1
Разбиение массива, как в Python (из библиотеки 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"
Допустим, я читаю массив от пользователя, тогда я хочу видеть элементы с 3 по 7 включительно.
cnt=0 while read var; do myarr[cnt]=$var cnt=$((cnt+1)) done echo ${myarr[@]:3:5}