반응형
Bash에서 배열을 슬라이스하는 방법
bash (1) 매뉴얼 페이지의 "Array"섹션을 보면 배열을 슬라이스하는 방법을 찾지 못했습니다.
그래서 나는이 지나치게 복잡한 기능을 생각해 냈습니다.
#!/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 )"
}
이런 식으로 사용 :
$ A=( foo bar "a b c" 42 )
$ slice B A 1 2
$ echo "${B[0]}" # bar
$ echo "${B[1]}" # a b c
더 좋은 방법이 있습니까?
Bash 페이지 의 Parameter Expansion 섹션을 man
참조하십시오. A[@]
배열의 내용을 반환하고 :1:2
인덱스 1부터 시작하여 길이 2의 슬라이스를 가져옵니다.
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
"ab c"가 하나의 배열 요소이며 추가 공간이 포함되어 있다는 사실이 유지됩니다.
지정된 인덱스로 시작하는 배열의 모든 요소를 가져 오는 편리한 바로 가기도 있습니다. 예를 들어 "$ {A [@] : 1}"은 배열의 "꼬리", 즉 첫 번째 요소가없는 배열입니다.
version=4.7.1
A=( ${version//\./ } )
echo "${A[@]}" # 4 7 1
B=( "${A[@]:1}" )
echo "${B[@]}" # 7 1
파이썬과 같은 배열 슬라이싱 ( 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}
참고 URL : https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash
반응형
'IT story' 카테고리의 다른 글
GPU 프로그래밍 소개 (0) | 2020.05.27 |
---|---|
파이썬에서 x **. 5 또는 math.sqrt (x) 중 어느 것이 더 빠릅니까? (0) | 2020.05.27 |
package.json에서 필요한 Node.js 버전을 지정하려면 어떻게해야합니까? (0) | 2020.05.26 |
“self.x = x; (0) | 2020.05.26 |
Java ClassLoader 란 무엇입니까? (0) | 2020.05.26 |