다음이 길이가 다른 배열을 제공하고 심지어 로 반환하는 이유를 알고 계십니까 "${distro[@]}"
?
금연 건강 증진 협회
#!/bin/bash
. ./two.sh
hello(){
arr=$(get_array)
echo "Length arr:" "${#arr[@]}" # array is not preserved and returns 1, but why?
show_length # returns length as correct 3
}
"$@"
2.sh
#!/bin/bash
get_array(){
distro=("redhat linux" "debian linux" "gentoo linux")
echo "${distro[@]}"
}
show_length(){
distro=("redhat linux" "debian linux" "gentoo linux")
echo "Length distro: ${#distro[@]}"
}
왜:
sh ./one.sh hello
Length arr: 1
Length distro: 3
답변1
가 있는 함수에서는 배열을 반환할 수 없습니다 echo "${distro[@]}"
. 그것이 하는 일은 함수의 표준 출력으로 인쇄하는 것뿐입니다. 이는 구조가 없는 바이트 스트림일 뿐이며 다른 배열 요소를 분리할 수 없습니다.
실제로 일어나는 일은 "${distro[@]}"
여러 가지 매개변수로 확장되어 모두 에 전달된 echo
다음 echo
인쇄되고 공백과 연결된다는 것입니다. 효과적으로 3개 요소 배열( redhat linux
, debian linux
, gentoo linux
)을 단일 문자열로 변환합니다 redhat linux debian linux gentoo linux
.
이에 따라 stdout을 문자열 로 읽고 .( 배열 할당이 포함되며 기본 설정을 사용하여 생성된 토큰화 및 와일드카드에 대한 명령 대체가 적용됨)에 할당 arr=$(get_array)
하는 스칼라 할당도 있습니다.get_array
arr
arr=( $(get_array) )
여섯 가지 요소이 출력의 배열( redhat
, linux
, debian
, linux
, gentoo
, ) 입니다. linux
)
해결 방법은 개행 문자를 구분 기호로 사용하여 배열 요소를 인쇄한 다음 일반 토큰화보다 더 스마트한 방법을 사용하여 반대쪽 배열로 읽는 것입니다.이름배열을 내부 함수에 전달하고 그 안에 데이터를 저장하도록 합니다.
readarray
(Bash 4.0 기준)을 사용하여 한 줄에 하나의 값을 인쇄합니다.
#!/bin/bash
foo() {
local arr=("foo bar" "doo")
printf "%s\n" "${arr[@]}"
}
readarray -t arr2 < <(foo)
printf "read %d elements: " "${#arr2[@]}"
printf "<%s> " "${arr2[@]}"
printf "\n"
그러나 배열이 비어 있으면 printf
개행 문자가 계속 인쇄되고 반대쪽 끝의 결과는 요소 배열이 됩니다.
또는 NUL 바이트를 구분 기호로 사용하여(Bash 4.4부터) 임의의 배열 요소를 전달하고 빈 배열 문제를 해결할 수 있습니다.
#!/bin/bash
foo() {
local arr=("foo bar" $'new\nline')
if (( ${#arr[@]} )); then
printf "%s\0" "${arr[@]}"
fi
}
readarray -t -d '' arr2 < <(foo)
# use declare -p for unambiguous shell-quoted output
declare -p arr2
또는 변수 이름을 전달하여 nameref를 사용하세요.
#!/bin/bash
bar() {
local arr=("foo bar" "doo")
declare -n _name="$1"
_name=("${arr[@]}")
}
bar arr2
printf "got %d elements: " "${#arr2[@]}"
printf "<%s> " "${arr2[@]}"
printf "\n"